mark (03/28/83)
Since the point of the macro I posted was to be portable across UNIX implementations (it certainly wasn't to generate wonderful random numbers on 4.1BSD - it should right shift 16 bits to do that, but this would lose portability; it turns out it does generate reasonable random numbers on 4.1), I'd like to share some improvements and corrections to it from Tom Duff: The macro #define randint(n) ( ((long) rand() & 0177777) * n / 0177777) has a bug. When rand() generates a number with 16 low-order 1-bits, which it does once in 65536 calls, on average, the result of the macro will be n, which is not in the range [0,n-1]. I believe that the following will work, however: #define randint(n) (int)(((long)rand()&077777)*(n)/0100000L) This will probably work on pdp11s, vaxs, SUNs and other 68000s and just about any other binary machine whose word length is 16 bits or more. I also fixed four other bugs. First, some versions of rand produce 15 bit results, so the mask 0177777 is one bit too big. Second, your randint would fail on the call randint(n+1) because of some missing parentheses. Third, the type of the result should probably be (int), not (long). Fourth, on 16 bit machines, 0177777 (and 0100000, which replaces it in my version) are negative numbers, and need to have an `L' appended to come out positive. On n bit machines, integer constants are implicitly made long if they are decimal and have more than n-1 bits precision, or if they are octal or hexadecimal and have more than n bits precision. 0177777 has only 16 bits precision, and therefore on a 16 bit machine is short and therefore -1. Unless, of course you're on a ones complement machine, in which case it's -0. And, of course on signed-magnitude machines, the value is -32767. If you wanted it to work on all machines, independent of number representation, you should probably rewrite it as: #define randint(n) (rand()%(P-1)*(n)/P) where P is the largest representable positive integer. In all fairness, only one of my four additional bugs makes a difference on a VAX. But if you claim portability, you should be able to back it up. The worst portability problems (at least in UNIX code, where you can mostly depend on system software compatibility) arise from data representation problems.