Apache OpenOffice (AOO) Bugzilla – Issue 116920
Sometimes RND returns 1 (one)
Last modified: 2017-05-20 11:27:37 UTC
Basic Rnd function SHOULD return pseudorandom value greater or equal than 0 and LESS than 1. So, 0 <= Rnd < 1 or [0; 1) interval. In OpenOffice.org it returns value greater or equal than 0 and LESS OR EQUAL than 1. Code: Sub TestRnd tries& = 10000000 s% = 0 For i& = 1 To tries If Rnd = 1 Then s = s + 1 Next MsgBox s / tries End Sub Expected result: 0 Result: 3,28E-05 (or near because of random values). This randomly breaks down an algorithms believing the Rnd value strictly LESS than 1 with out of bound errors. Same behaviour in OOo 3.3.0, 3.1.1, 2.4.3.
Andreas, please have a look.
Please, consider this along with issue 14730
This seems to be Windows OS problem. On Linux the macro above gives 0.
I can not reproduce this bug on 32-bit linux biulds of OOo (tested on Slackware- 13.1, Fedora-14, Ubuntu-10.04). So, OS field has been changed to Windows. I can not agree that the problem is OS, not the OOo build for Windows. The Linux Programmers Guide says that the rand() function returns a pseudo- random integer in the range [0, RAND_MAX]. MSDN has similar description. Current OOo Basic RND implementation doesn't contain any differences for Win/Lin: basic/source/runtime/methods.cxx RTLFUNC(Rnd) { (void)pBasic; (void)bWrite; if ( rPar.Count() > 2 ) StarBASIC::Error( SbERR_BAD_ARGUMENT ); else { double nRand = (double)rand(); nRand = ( nRand / (double)RAND_MAX ); rPar.Get(0)->PutDouble( nRand ); } } So, the only reason is used C/C++ compiler runtime: rand() returns [0;RAND_MAX) on Linux and [0;RAND_MAX] on Windows. May be (quick and dirty) #IFDEF (<something_unique_for_this_win_compiler>) // srand() returns [0;RAND_MAX] nRand = ( nRand / ((double)RAND_MAX + 1.)); #ELSE // srand() returns [0;RAND_MAX) nRand = ( nRand / (double)RAND_MAX ); #ENDIF 32766/32767 = 0,999969481 32766/32768 = 0,999938965 32767/32768 = 0,999969482 And if we can agree with maximum RND values 0,999938965 on Linux and 0,999969482 on Windows, too more dirty: nRand = ( nRand / ((double)RAND_MAX + 1.));
ScRandom() in interpr1.cxx has been changed to return values from [0;1[ with issue 53642. I think, that Basic should return the same range as Calc. ScRandom() uses PushDouble((double)rand() / ((double)RAND_MAX+1.0)); For VB you find the description "The Rnd function returns a value less than 1, but greater than or equal to zero." [http://msdn.microsoft.com/en-us/library/f7s023d2(VS.90).aspx#Y1057]
So, for 32 bit int 2147483646 / 2147483647 = 0,9999999995 2147483646 / 2147483648 = 0,9999999991 2147483647 / 2147483648 = 0,9999999995 and else { double nRand = (double)rand(); nRand = ( nRand / (double)RAND_MAX ); rPar.Get(0)->PutDouble( nRand ); } can be simple replaceced with else rPar.Get(0)->PutDouble( (double)rand() / ((double)RAND_MAX + 1. )
else rPar.Get(0)->PutDouble( (double)rand() / ((double)RAND_MAX + 1.) );
http://msdn.microsoft.com/en-us/library/398ax69y.aspx says, that MS VC 2010 still use 32767 as RAND_MAX for rand(). If this is true, we get 32767/32768 = 0,999969482 max with 1/32768 granularity on Windows, 2147483647/2147483648=0,9999999995 max with 1/2147483648 granularity on Linux. It is even slightly better than it was :-) . So, (double)rand()/((double)RAND_MAX+1.) is good enough.
bormant, you mean that this issue affects not only Windows, just it happens very rarely? I.e., if you run the macro in OP with 10 000 000 replaced by, e.g., something more than 2147483647 ? Then this fix would fit for all OSes.
Reset assigne to the default "issues@openoffice.apache.org".