Reputation: 10204
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
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
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
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