Page 1 of 1

RND related question

Posted: Sat Apr 28, 2018 6:49 pm
by R-Tape
Okayyy, I should know this by now but I'll blame it on my rusty BASIC.

I'd like to get random integers starting at 0 and up to and including 186.

Theoretically my understanding is that:

INT (RND*186)

Should do it but it never gives 186, even with the processor put up and leaving it. If I change it to:

INT (RND*187)

It gives 186, and never seems to give 187. The BASIC manual says that RND=1 is a possibility, is that right? What have I misunderstood or does RND=1 happen once in a google billion?

Re: RND related question

Posted: Sat Apr 28, 2018 6:53 pm
by AndyC
According to Chapter 11, it can be 0 but never 1, which is how I always understood it. Since Sinclair BASIC always rounds down, RND*186 can never give 186.

Re: RND related question

Posted: Sat Apr 28, 2018 6:54 pm
by MatGubbins
186 gives 0 to 185
If you want 186 then int (rnd*186)+1, then you should get 1 to 186
unless my basic is rusty too.

Re: RND related question

Posted: Sat Apr 28, 2018 6:59 pm
by Blerkotron
Yeah, it was always my understanding that RND returned a number of 0 or greater but always less than 1, therefore INT(RND*187) would give you what you want. If it's possible for RND to return a value of 1 I've never seen it happen!

Re: RND related question

Posted: Sat Apr 28, 2018 7:01 pm
by MonkZy
I think INT ((RND*186)+0.5) would give 0 to 186

Re: RND related question

Posted: Sat Apr 28, 2018 7:08 pm
by Einar Saukas
R-Tape wrote: Sat Apr 28, 2018 6:49 pm INT (RND*186)
In theory, it generates a number from 0 to 185.

In practice, in many BASIC implementations there's a very small change of producing 186, due to floating point rounding errors.

Re: RND related question

Posted: Sat Apr 28, 2018 7:10 pm
by Einar Saukas
MonkZy wrote: Sat Apr 28, 2018 7:01 pm I think INT ((RND*186)+0.5) would give 0 to 186
Yes, but values 0 and 186 would have only half the chance of any other.

Re: RND related question

Posted: Sat Apr 28, 2018 8:22 pm
by Kweepa
if you really want to bulletproof your code, then perhaps
def fn r(x)=int(rnd*(x+0.9999))
let p=fn r(186)
Or, if you can't abide the last number being marginally less probable,
let p=int(rnd*187): let p=p*(p<>187)
which will set p=0 if it ever hits 187.
I don't think these are necessary though.
Sadly the Spectrum manual suggests int(rnd(x+0.5)) :(

Re: RND related question

Posted: Sat Apr 28, 2018 8:34 pm
by Kweepa
Some more thought...
Spectrum uses RNG that produces a sequence that runs through 0-65535, which RND just divides by 65536.
You can see this by running the program:
10 print 65536*rnd:goto10
Therefore the max that RND can produce is 65535/65536=0.999984 (calc done on spectrum)
When you multiply, for example, 187 by that, you get 186.99715 (calc done on spectrum) which will never round accidentally to the higher number.
So it's perfectly safe to use INT(RND(187)) for 0-186.

Re: RND related question

Posted: Sat Apr 28, 2018 8:56 pm
by Einar Saukas
Kweepa wrote: Sat Apr 28, 2018 8:34 pm Some more thought...
Spectrum uses RNG that produces a sequence that runs through 0-65535, which RND just divides by 65536.
You can see this by running the program:
10 print 65536*rnd:goto10
Therefore the max that RND can produce is 65535/65536=0.999984 (calc done on spectrum)
When you multiply, for example, 187 by that, you get 186.99715 (calc done on spectrum) which will never round accidentally to the higher number.
So it's perfectly safe to use INT(RND(187)) for 0-186.
Good point!

So it's safe specifically for Sinclair BASIC, for the wrong reason :)

Re: RND related question

Posted: Sat Apr 28, 2018 9:09 pm
by R-Tape
Interesting! Thanks.

I didn't unravel the maths but after a few minutes with the emulator cranked up I was fairly sure 187 was not going to appear.

INT(RND(187)) it is.