Im trying to generate random integers with logarithmic distribution. I use the following formula:
idx = Math.floor(Math.log((Math.random() * Math.pow(2.0, max)) + 1.0) / Math.log(2.0));
This works well and produces sequence like this for 1000 iterations (each number represents how many times that index was generated):
[525, 261, 119, 45, 29, 13, 5, 1, 1, 1]
Fiddle
I am now trying to adjust the slope of this distribution so it doesn't drop as quickly and produces something like:
[150, 120, 100, 80, 60, ...]
Blindly playing with coefficients didn't give me what I wanted. Any ideas how to achieve it?
Im trying to generate random integers with logarithmic distribution. I use the following formula:
idx = Math.floor(Math.log((Math.random() * Math.pow(2.0, max)) + 1.0) / Math.log(2.0));
This works well and produces sequence like this for 1000 iterations (each number represents how many times that index was generated):
[525, 261, 119, 45, 29, 13, 5, 1, 1, 1]
Fiddle
I am now trying to adjust the slope of this distribution so it doesn't drop as quickly and produces something like:
[150, 120, 100, 80, 60, ...]
Blindly playing with coefficients didn't give me what I wanted. Any ideas how to achieve it?
Share Improve this question asked Jun 8, 2015 at 22:24 sergserg 111k78 gold badges325 silver badges337 bronze badges 3-
1
set every
2.0
in you formula closer to1.0
e,g.1.3
– zmii Commented Jun 8, 2015 at 22:28 -
@zmii that works well if
max=10
, but ifmax=2
it produces even sharper slope:[830, 170]
vs[744, 256]
for2.0
– serg Commented Jun 8, 2015 at 22:32 - I do it like this: pseudo random numbers with a predefined distribution – Spektre Commented Jun 9, 2015 at 6:26
1 Answer
Reset to default 7You mention a logarithmic distribution, but it looks like your code is designed to generate a truncated geometric distribution instead, although it is flawed. There is more than one distribution called a logarithmic distribution and none of them are that mon. Please clarify if you really do mean one of them.
You pute floor[log_2 U] where U is uniformly distributed from 1 to (2^max)+1. This has a 1/2^max chance to produce max, but you clamp that to max-1. So, you have a 1/2^max chance to produce 0, 2/2^max chance to produce 1, 4/2^max chance to produce 2, ... up to a 1/2 + 1/2^max chance to produce max-1.
Present in your code, but missing from the description in the question, is that you are flipping the puted index around with
idx = (max-idx) - 1
After this, your chance to produce 0 is 1/2 + 1/2^max, and your chance to produce a value of k is 1/2^(k+1).
I think it is a mistake to let U be uniform on [1,2^max+1]. Instead, I think you want U to be uniform on [1,2^max]. Then your chance to generate idx=k is 2^(max-k-1)/((2^max)-1).
idx = Math.floor(Math.log((Math.random()*(Math.pow(2.0, max)-1.0)) + 1.0) / Math.log(2.0));
zmii's ment that you could get a flatter distribution by replacing both 2.0s with a value closer to 1.0 is good. The reason it produced unsatisfactory results for small values of max was that you were sampling uniformly from [1,1.3^max+1] instead of [1,1.3^max]. The extra +1 made a larger difference when max was smaller and the base was smaller. Try the following:
var zmii = 1.3;
idx = Math.floor(Math.log((Math.random()*(Math.pow(zmii, max)-1.0))+1.0) / Math.log(zmii));
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745368797a4624704.html
评论列表(0条)