anon
anon

Reputation: 560

C# Random Floating Point Closed Interval

I'm surprised I couldn't find an answer to this anywhere, so perhaps I'm missing something.

The NextDouble method of the System.Random class returns doubles within the range of [0.0,1.0). This is a half-open interval which returns 0.0 <= x < 1.0.

I need a closed interval [0.0,1.0] such that 0.0 <= x <= 1.0. In C++, I could use std::nextafter, which returns me the smallest representable floating point that is greater than the passed parameter (e.g. std::nextafter(1.0, 2.0) would return 1.0000001192092895508). I can't seem to find an equivalent in C#.

I'm working with tons of highly precise numbers (16bit), so although 1.0 may seldom appear, I still need it to have the ability to. And although the difference between 1.0 and 1.0000001192092895508 may seem negligible (and often is), the difference is one that will matter in this case.

After implementing a solution similar to this version of NextAfter, I sometimes get numbers larger than the maximum (e.g. 5.00000027008353 for [0.0,5.0])

Random.NextDouble() * ((NextAfter(max, max + 1.0) - min) + min);

How can I generate random floating point numbers with a closed interval? I'm going to be executing this many times so preferably something that does not take too long to execute (like calling Random multiple times or using while loops and rejection sampling). Also, it's necessary to be unbiased, yielding uniform results (i.e. no number should be more likely to appear than any other number).

Upvotes: 3

Views: 460

Answers (2)

Eric Lippert
Eric Lippert

Reputation: 659964

This seems straightforward:

  • Decide how often you want 1.0 to appear on average. Say, one in every billion times.
  • Generate a random integer between zero and two billion from the bell shaped distribution with mean of a billion of your choice. Call it n.
  • Generate n random numbers on the open interval.
  • Generate 1.0.
  • Repeat.

Now you've got a sequence of random numbers on the closed interval where 1.0 appears the expected number of times on average. You get one expensive bell-shaped computation every billion or so, which amortizes out to basically zero cost.

Upvotes: 2

PepitoSh
PepitoSh

Reputation: 1836

Your bit representation of floats implies a limited number of distinct values. Determine the number of possible float values, get a random int in that range and map/convert this value to your float range.

Upvotes: 0

Related Questions