Path: csiph.com!eternal-september.org!feeder.eternal-september.org!reader01.eternal-september.org!.POSTED!not-for-mail From: Tim Rentsch Newsgroups: comp.lang.c Subject: Re: Bart, a tcc "issue" Date: Fri, 08 Nov 2019 20:59:34 -0800 Organization: A noiseless patient Spider Lines: 59 Message-ID: <86k189ejbd.fsf@linuxsc.com> References: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: reader02.eternal-september.org; posting-host="bd07fdb0e7610947dc98257bdadc7724"; logging-data="3889"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX1+s2TPt+mEUSqbSFvbopo/kTQ5o+C2PuTM=" User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.4 (gnu/linux) Cancel-Lock: sha1:uAzLsEegL9q4I5w2EuA0ug16thU= sha1:YuzzkwAVBE15QnAsWeePLp18S04= Xref: csiph.com comp.lang.c:147809 Richard Damon writes: > On 11/6/19 6:40 PM, DFS wrote: > >> I wrote a distribution of characters counter, and on tcc (0.9.26) on >> Windows it always undercounts the last character in the set (9). If you >> have tcc on Windows maybe you could test it. Doesn't happen on >> gcc/MSYS2/Windows. > > This is a fundamental problem. A very simple version of it would be to > try to take 12 apples and divide them into 5 (or 7) equal piles (without > cutting any of them). > > The 12 apples are the RAND_MAX possible values. > > The 5 piles are the buckets you are putting them into. > > If the number of buckets doesn't exactly divide into the number of > results you can get from the random number generator, the output won't > be equally likely. This most noticeable when the number of possible > numbers is smaller. > > The simplest solution would be to throw away a few of the random > numbers, so that the number of 'usable' random numbers is a multiple of > the number of buckets. > > The simple modification to the code is rather than using: > (low + rand() / (RAND_MAX / (high - low + 1) + 1)) > use > (low + rand() / (RAND_MAX / (high - low + 1))) > and redraw if the result is > high. It's interesting -- three different people posted corrections or improvements to the uniform interval code, and all of the revisions have been a little bit off in one way or another. Care is needed to deal with edge cases correctly. int uniform_less_than( unsigned k ){ unsigned d, r; if( k-1 > RAND_MAX || k == 0 ) oops_someone_messed_up(); d = (RAND_MAX - (k-1)) / k + 1; do r = rand()/d; while( r >= k ); return r; } int uniform_on_closed_interval( int a, int b ){ if( a > b ) return uniform_on_closed_interval( b, a ); return a + uniform_less_than( b + 1u - a ); } A good test for a uniform closed-interval RNG is to check that it handles the interval 0..RAND_MAX, including both endpoints, correctly.