1

I wrote the following 4-liner in C as a helper function, but I now find it useful beyond what I had anticipated and would like to cover it in my tests.

double random_double_in_range(double min, double max) {
    // This cannot overflow, no matter the values of min, max and x.
    // It will return an uniformly distributed double
    // between min and max, inclusive.
    int n = rand();
    if (n==0) return min;
    double x = (double) n;
    return x * (max / RAND_MAX - min / RAND_MAX + min / x);
}

I wrote the comment and believe it to be true, but how can I really without tests?

I can easily test that the returned value is within the bounds, but how can I write a test that determines whether it is actually uniformly distributed? If I simply run it one million times and check that it fits a uniform distribution within some tolerance, eventually it will exceed that tolerance and fail spuriously.

I know that probably there exist libraries that do this already; this is more of a personal exercise (how do they do their testing?)

Riccardo Orlando
  • 207
  • 2
  • 10
  • 2
    Does this answer your question? [How to unit test a pseudo random number generator?](https://stackoverflow.com/questions/186619/how-to-unit-test-a-pseudo-random-number-generator) – mousetail Sep 30 '20 at 14:36
  • Without seeing the specifications (detailed enumeration of what the function is supposed to do.) it will be impossible to properly know how to test. E.g. does the range of acceptable inputs include negative values? BTW, this expression: `(x == 0)` is not useful when dealing with `double` comparisons. i.e. `0.00000000001` may be close enough to zero, but it will not pass the comparison. – ryyker Sep 30 '20 at 14:37
  • `how can I write a test that determines whether it is actually uniformly distributed?` Split [min,max] into `n` subranges with equal size. Keep count associated with each subrange. Generate one value. Increment the count associated with the subrange the value falls in. Repeat for as many values depending on the precision you want to get. If the counts of subranges are (approaching to be) equal, means it's uniform. Ie. do a histogram and see if it's a straight line. – KamilCuk Sep 30 '20 at 14:39
  • @mousetail Yeah, it convinced me that I cannot. – Riccardo Orlando Sep 30 '20 at 14:40
  • @ryyker The specifications are in the comment to the function - uniformly distributed between min and max, which can be any double value. Thanks for the == suggestion - I'll do the checking before casting to double. – Riccardo Orlando Sep 30 '20 at 14:41
  • @KamilCuk If I automate that, eventually it's bound to fail spuriously. – Riccardo Orlando Sep 30 '20 at 14:41
  • _"The specifications are in the comment to the function..."_ By the specifications then, it fails any code review: The function is prototyped to return `double` but is spec'd to return `float` ( _It will return an uniformly distributed float_ ). – ryyker Sep 30 '20 at 14:45
  • It depends what you mean by "uniformly distributed". `rand()` can only return `RAND_MAX+1` different values and there may be more than that number of representable values in a `double` between `min` and `max`. – Ian Abbott Sep 30 '20 at 14:46
  • @ryyker: `x == 0` is fine for testing whether a `double` is zero or not. `rand` returns an integer, and there is no way any other integer will produce zero in `x` or that zero will produce non-zero in `x`. – Eric Postpischil Sep 30 '20 at 14:47
  • @ryyker Yeah, that was a silly typo of mine. Thanks, fixed. – Riccardo Orlando Sep 30 '20 at 14:48
  • Should the specifications include that the function `srand(...)` is required to be called prior to calling this one? – ryyker Sep 30 '20 at 14:48
  • @IanAbbott That makes sense. I may just give up on this approach. – Riccardo Orlando Sep 30 '20 at 14:49
  • @ryyker I don't know. From what I know, `rand()` works fine even if `srand()` wasn't called, albeit by always returning the same sequence of values. – Riccardo Orlando Sep 30 '20 at 14:50
  • @IanAbbott - Yes, I attempted to make it a general observation about `==` when comparing any _floating_ type, but did not sufficiently make that clear in the comment. Thank you for clarifying the point! – ryyker Sep 30 '20 at 14:52

1 Answers1

0

Use the DieHarder framework. It will warn you if you have problems with the generated numbers. The usage of the rand() function is already a problem because it does not pass DieHarder tests.

Todor Balabanov
  • 376
  • 3
  • 6
  • 17