Why does Rnd work this way?

BlitzMax Forums/BlitzMax Beginners Area/Why does Rnd work this way?

big10p(Posted 2008) [#1]
I see that Rnd(min_val,max_val) works differently from Blitz3D inasmuch as max_val is exclusive. Why is this?

So now how do i get a random number in the inclusive range 0.0 to 1.0, for example?

I also see that Rand()'s parameters are both inclusive...


tonyg(Posted 2008) [#2]
scrub that... need to read better


GfK(Posted 2008) [#3]
So now how do i get a random number in the inclusive range 0.0 to 1.0, for example?

Just use Rnd(0,1). Never concerned myself with all that inclusive/exclusive lark. When you're returning a double the chances of that double being exactly 1 would be miniscule anyway.

Just ran a couple of hundred iterations and the highest I got was 0.99442527370318512. Do you need it more precise than that?


big10p(Posted 2008) [#4]
Do you need it more precise than that?
Probably not, now you mention it. I was just wondering why it differed from the other blitz languages, really. I also need to get used to the increased precision offered by Doubles, as I've not had to use them in a good while. :)


Floyd(Posted 2008) [#5]
The floating point value Rnd(a,b) is in the range from a to b, where a is included but b is excluded. This is the way it works in all versions of Blitz and all other languages I can think of.

It is a natural consequence of the way floats work. Imagine a simplified system with exactly three decimal digits. To generate a random float we generate three random digits. There are one thousand possible values uniformly distributed in the range 000 to 999. Now we put a decimal point at the front to get values from .000 to .999, which includes 0 but not 1.

So that's our random x from 0 to 1, with 1 excluded. For the range a to b we generate x as before, then calculate ( a + x * ( b - a ) ). This ranges from a to b ,with b excluded.

That's exacly how Rnd() works, except with random binary bits instead of random decimal digits.


big10p(Posted 2008) [#6]
Well, the Blitz3D docs say:

This returns either a floating point or integer number of a random value falling between the start and end number. It returns an integer if assiged to an integer variable, and it returns a floating point value if assiged to a floating number variable. The start and end values are inclusive.



Your explanation does make sense though, Floyd. Maybe the docs are wrong - wouldn't be the first time. :)


Floyd(Posted 2008) [#7]
It returns an integer if assiged to an integer variable, and it returns a floating point value if assiged to a floating number variable.

That's wrong no matter what else the function does. The returned value is always floating point, single precision for classic Blitz languages and double for BlitzMax.

Of course, if assigned to an integer variable then the value is converted to an integer. For example "n% = Rnd(1,4)" can only produce the results 1,2,3 in BlitMax.

But in earlier Blitz languages the conversion is done by rounding to the nearest integer. Hence the possible values are 1,2,3,4. This is no doubt the source of confusion about the end of the range being included.

It also a source of error. The length of the interval is 3. The integer results 1,2,3 in BlitzMax are equally likely, each occuring about 1/3 of the time. But the 1,2,3,4 of older Blitzes are not equally likely. The 2 and 3 each have probability 1/3, but the 1 and 4 split the other 1/3. This was particularly problematic in Blitz's early days when there was no Rand function.


Floyd(Posted 2008) [#8]
Sheesh, talk about lazy! I've just now read the Blitz3D description of Rnd() all the way through.
It actually uses the faulty "y = Rnd(0,10)" in the example code.

Here is a demostration of the difference.

In BlitzMax the numbers 1,2,3 occur with counts near 1000,1000,1000.
In Blit3D the numbers 1,2,3,4 occur with counts near 500,1000,1000,500.

Global count[5]   ;'   This array syntax works with both BlitzMax and Blitz3D etc.


Print
Print "  Count occurences of 1,2,3,4."
Print
For n = 1 To 3000
	r = Rnd(1,4)
	count[r] = count[r] + 1
Next

For n = 1 To 4
	Print n + "  " + count[n]
Next

WaitKey



Grey Alien(Posted 2008) [#9]
@Big10p: I never knew that, but I too don't worry about it as that chance of hitting a full rounded integer as the top number is so rate.


big10p(Posted 2008) [#10]
Interesting stuff, Floyd!


slenkar(Posted 2008) [#11]
Rand is inclusive though

e.g.

For x=1 To 100000
random=Rand(1,10)
If random=10
RuntimeError "arg"
EndIf
Next




big10p(Posted 2008) [#12]
I know, I mentioned that in my first post. ;)