| View previous topic :: View next topic |
| Author |
Message |
Thor Guest
|
Posted: Fri Apr 25, 2008 9:19 pm Post subject: Bell curve? |
|
|
| I want to generate a value x on a scale 0-200. I want the most probable value to be 100 and the least probable values to be 0 and 200. Like in a bell curve. How can I do this in AHK? |
|
| Back to top |
|
 |
engunneer
Joined: 30 Aug 2005 Posts: 6307 Location: Pacific Northwest, US
|
Posted: Fri Apr 25, 2008 9:27 pm Post subject: |
|
|
brute force way
| Code: |
range = 60
rolls = 50000
loop, %rolls%
{
random a, 0, % range/2
random b, 0, % range/2
randomnumber := round(a + b)
number%randomnumber%++
}
output =
SetFormat, Float, 4.2
loop, %range%
{
output .= A_index . "`t" . number%A_index% . "`t" . 100*(number%A_index%/rolls) . "%`n"
}
msgbox, %output%
|
This is based on the idea that two dice rolled together will have bell curve results, since more combinations add up to 7 than other numbers.
you can see the percents give a pretty nice shape.
further analysis shows that this generates more of a triangle than a bell.
see here for a better formula _________________
Unless otherwise noted, all code is untested.
Common Answers: 1.(Loops, Viruses, etc.) 2. Search 3.RTFM |
|
| Back to top |
|
 |
dncarac
Joined: 31 Aug 2006 Posts: 60
|
Posted: Sat Apr 26, 2008 2:51 am Post subject: |
|
|
The previous response was based on the law of large numbers. Here a page with a more mathematical explanation. It depends on how accurate you want the distribution to be.
http://www.taygeta.com/random/gaussian.html
DNC |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 3941 Location: Pittsburgh
|
Posted: Sat Apr 26, 2008 3:34 am Post subject: |
|
|
| If you want random integers of close to normal distribution, the simplest could be to add 10 uniform random numbers each between 0 and 20 (providing a binomial distribution.) Adding fewer numbers can be faster, but the distribution is less accurate. The best is adding 200 [0,1] random numbers. |
|
| Back to top |
|
 |
engunneer
Joined: 30 Aug 2005 Posts: 6307 Location: Pacific Northwest, US
|
Posted: Sat Apr 26, 2008 5:47 pm Post subject: |
|
|
Thanks Laszlo, that makes sense to me.
int mode has a larger standard deviation than float mode
| Code: |
;test random number distributions
starttime := A_now
range = 20
rolls = 200000
mode = int
;mode = float
loop, %rolls%
{
;code to generate random number starts here
randomnumber = 0
loop, %range%
{
If (mode = "int")
random, rand, 0, 1
else if (mode = "float")
random, rand, 0.0, 1.0
randomnumber += rand
}
randomnumber := round(randomnumber)
;code to generate random number ends here
number%randomnumber%++
}
output =
SetFormat, Float, 4.2
loop, %range%
{
output .= A_index . "`t" . number%A_index% . "`t" . 100*(number%A_index%/rolls) . "%`n"
}
endtime := a_now
elapsedtime := endtime
elapsedtime -= starttime, seconds
SetFormat, Float, 0.6
randomtime := elapsedtime / rolls
output.= "Elapsed time = " . elapsedtime . " seconds`tPer number = " . randomtime . " seconds"
msgbox, %output%
|
200000 rolls takes a minute on my computer for a range of 20
| Code: |
1 3 0.00%
2 31 0.02%
3 223 0.11%
4 891 0.45%
5 2920 1.46%
6 7486 3.74%
7 14857 7.43%
8 24318 12.16%
9 31845 15.92%
10 35250 17.63%
11 31821 15.91%
12 24121 12.06%
13 14713 7.36%
14 7355 3.68%
15 2975 1.49%
16 925 0.46%
17 230 0.11%
18 31 0.02%
19 5 0.00%
20 0.00%
Elapsed time = 62 seconds Per number = 0.000310 seconds
|
_________________
Unless otherwise noted, all code is untested.
Common Answers: 1.(Loops, Viruses, etc.) 2. Search 3.RTFM |
|
| Back to top |
|
 |
Thor Guest
|
Posted: Sat Apr 26, 2008 6:09 pm Post subject: |
|
|
| That's prefect! Thanks to all of you: engunneer, Laszlo, dncarac! |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 3941 Location: Pittsburgh
|
Posted: Sat Apr 26, 2008 7:09 pm Post subject: |
|
|
| The more random numbers you add, the less the standard deviation will be (proportional to 1/sqrt(n)). |
|
| Back to top |
|
 |
Thor Guest
|
Posted: Sat Apr 26, 2008 7:22 pm Post subject: |
|
|
| Is it possible to vary the spread of the curve? To make it higher or more flat in the middle. |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 3941 Location: Pittsburgh
|
Posted: Sat Apr 26, 2008 7:57 pm Post subject: |
|
|
| If you want integers, the only thing you can vary is the number of random values added together. Five look already pretty close to normal. If you want real numbers, add 25 of [-1,1] uniform random numbers and scale the result (multiply with the desired standard deviation times sqrt(3)/5, and add the desired mean value). |
|
| Back to top |
|
 |
Thor Guest
|
Posted: Sat Apr 26, 2008 11:28 pm Post subject: |
|
|
Huge thanks Lazlo! Both for taking your time and for helping me with this I wouldn't have been able to solve on my own! I understand everything but this:
sqrt(3)/5
Why is it not enough to use just one constant? Is it the same effect as some constant but this way we turn it into real sample standard deviation language?
Where do the numbers 3 and 5 come from? |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 3941 Location: Pittsburgh
|
Posted: Sat Apr 26, 2008 11:48 pm Post subject: |
|
|
| The standard deviation of a uniform random variable in [-1,1] is 1/sqrt(3), we add 25 of such variables together, which increases this standard deviation sqrt(25) = 5 fold. If you don’t like the sqrt(3) term, you can add 27 random variables together, which makes this constant sqrt(3)/sqrt(27) = 1/3. Adding only 12 variables together makes this constant 0.5. |
|
| Back to top |
|
 |
Thor Guest
|
Posted: Sun Apr 27, 2008 12:34 am Post subject: |
|
|
How does this look?
| Code: |
#SingleInstance, Force
; CONFIG
mean = 100
SD = 10
dices = 20
rolls = 100000
; GENERATION
loop, % rolls
{
randomnumber = 0
loop, % dices
{
random, rand, -1.0, 1.0
randomnumber += rand
}
randomnumber := randomnumber * sqrt(3)/sqrt(dices)
randomnumber += mean
randomnumber := Round(randomnumber)
number%randomnumber%++ ;representation
}
; REPRESENTATION
SetFormat, Float, 4.2
loop, % 20
{
R_Index := mean - 10 + A_Index
output .= R_index "`t" number%R_index% "`t" 100*(number%R_index%/rolls) "%`n"
}
msgbox, %output%
|
The distribution seems to change somewhat when I change the value of "dices". Is this because of the factor "sqrt(3)/sqrt(dices)"? I guess the distribution wouldn't change if we didn't have that factor?
I don't know if I'm guessing correctly. If you can help explain sort this out to me then it's even more awesome++. But your help has already been awesome beyond google. |
|
| Back to top |
|
 |
Thor Guest
|
Posted: Sun Apr 27, 2008 12:41 am Post subject: |
|
|
Hmmm... I see that is not the case. I understand now that the more [-1, 1] units I add the larger the spread will be. I guess "sqrt(3)/sqrt(dices)" was an attempt to neutralize this.
I still seemed to be getting more percent in the middle with higher dices... I'm really curious about this. Interesting stuff. |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 3941 Location: Pittsburgh
|
Posted: Sun Apr 27, 2008 1:02 am Post subject: |
|
|
| I ran your script with dices = 4, 20 and 40, and got very similar results, which is what expected. |
|
| Back to top |
|
 |
Mkbailey755
Joined: 20 Aug 2007 Posts: 157
|
Posted: Sun Apr 27, 2008 2:02 am Post subject: |
|
|
Dont need to hijack this thread but what does
| Code: | | output .= A_index . "`t" . number%A_index% . "`t" . 100*(number%A_index%/rolls) . "%`n" |
Mainly the A_index I dont understand also the 'n I think this is a Square root(sqrt) function? if someone could break this line down as if I was a child much appreciated |
|
| Back to top |
|
 |
|