/usr/games/random bug?

Peter Wemm peter at wemm.org
Wed Dec 22 23:25:36 PST 2004


On Monday 20 December 2004 05:13 pm, James R. Van Artsalen wrote:
> 5-stable "/usr/games/random -e 99" seems to always return 0, which
> makes it very predictable.
>
> 5.2.1 does this too.  But i386 4.x seems to work as expected (an exit
> value between 0 and 98 inclusive).
>
> The source code line in question is
>
>               return (int)((denom * random()) / LONG_MAX);
>
> the assembler code is
>
>         .p2align 3
> .LC17:
>         .long   0
>         .long   1006632960
>
>         call    random
>         cvtsi2sdq       %rax, %xmm0
>         mulsd   24(%rsp), %xmm0
>         mulsd   .LC17(%rip), %xmm0
>         cvttsd2si       %xmm0, %eax
>         jmp     .L1
>
> I'm not familiar enough with IEEE fp rules or amd64 fp coding to say
> why this doesn't work, nor if this source code is even reasonable.

The problem is a code design error and/or invalid assumptions about the 
range of values that random() returns..

random() returns a long.
However, random()'s range is limited to 31 bits. 

"DESCRIPTION
The random() function uses a non-linear additive feedback random number
generator employing a default table of size 31 long integers to return
successive pseudo-random numbers in the range from 0 to (2**31)-1.  The
period of this random number generator is very large, approximately
16*((2**31)-1)."

Now,  We're taking a 2^31 bit number, and multiplying it by some integer 
value, eg: 99.

Then dividing the result by LONG_MAX, which is 2^62.

Now, the result of  (large but not so large number) divided by (much 
larger number (a billion times larger!)) is always = 0.

Try changing the LONG_MAX in that division to INT_MAX and it will behave 
the same as on i386.

Then we have (n * (0 .. 2^31)) / (2 ^ 31)  which makes much more sense.  
And it even works on both 32 and 64 bit systems.
-- 
Peter Wemm - peter at wemm.org; peter at FreeBSD.org; peter at yahoo-inc.com
"All of this is for nothing if we don't go to the stars" - JMS/B5


More information about the freebsd-amd64 mailing list