zell
zell

Reputation: 10204

Generate a random floating point, with no range constraint, but including +inf, -inf, NaN, in python

Python's random number generator allows us to generate a floating point in some range. I wonder how can we generate a floating point number without the range constraint. The random floating point number I want to generate can be NaN, +inf, -inf, or any number in between the minimal and maximal floating point number.

I am looking for a pythonic solution. Thanks.

Upvotes: 1

Views: 716

Answers (3)

Vlad
Vlad

Reputation: 9481

One way to do that is to generate some random integers/bytes and convert them to float using struct.unpack. Since a quite a few byte combinations are actually not valid floating point numbers you will get a lot of NaNs. INFs are bit trickier you will only get them if your random bytes combination happens to be just right. Look here here for more details.

Upvotes: 3

krethika
krethika

Reputation: 4476

The excellent testing library hypothesis may suit your needs if you are generating the numbers as part of a test suite. This will not answer your case of a "random" float, but I believe that is impossible anyway if including nan and inf numbers. What it will do is generate a bunch of float values in an attempt to cover edge cases.

>>> from hypothesis.strategies import floats
>>> get_float = floats().example

>>> get_float
WrapperFloatStrategy(GaussianFloatStrategy() | BoundedFloatStrategy() 
   | ExponentialFloatStrategy() | JustIntFloats() |
   SampledFromStrategy((0.0, 2.2250738585072014e-308, 
   -2.2250738585072014e-308, -1.7976931348623157e+308,    
   1.7976931348623157e+308, inf, -inf, nan)) | FullRangeFloats())

>>> get_float()
-1.7976931348623157e+308
>>> get_float()
inf
>>> get_float()
49215.0 

As you can see, it will generate a random-ish number fitting the properties of a float, including inf, -inf, and nan.

Upvotes: 2

John Coleman
John Coleman

Reputation: 51998

Standard pseudo-random number generators which return values in a range [a,b] are simulations of uniform random variables on [a,b] -- something which has a clear mathematical model. There simply doesn't exist any uniform distribution on [-infinity, +infinity], so it isn't clear what you are trying to simulate. In any reasonable interpretation of what you are trying to do, +inf and -inf would be vanishingly rare -- so why even bother? You could somewhat arbitrarily decide that you want -inf, +inf to occur a certain percentage of the time (say 1 in a million) and write a function which return -inf on average 1 in a million time, + inf 1 in a million times, and the remaining times return a randomly chosen number in a large range of floats. Something like:

def extendedRandom(a,b,infProb):
    myRoll = random.random()
    if myRoll < infProb:
        return float('-inf')
    elif myRoll < 2*infProb:
        return float('+inf')
    else:
        return random.uniform(a,b)

Used like thus:

>>> for i in range(20):
    print(extendedRandom(-10**15,10**15,0.2))

-inf
inf
339184853623024.5
936746547842162.5
211578440289046.5
inf
-654872390518085.2
524487814975436.5
250131763600250.75
-inf
-880823611470973.4
inf
354024482521076.75
-369458678524420.25
inf
-537391531707519.94
-inf
-298740652509172.0
-inf
-inf

Ad hoc -- but if you want a random number generator which throws out a + or - inf at times then this would work.

Upvotes: 3

Related Questions