Say I have two Python floats a
and b
, is there an easy way to find out how many representable real numbers are between the two in IEEE-754 representation (or whatever representation the machine used is using)?
-
1Just out of curiosity, what do you need this information for? – Matti Virkkunen Aug 27 '10 at 20:30
-
How do you mean? Two specific floats or generally? And do you want to be able to do this from python or do you want to make the calculations manually? – terminus Aug 27 '10 at 20:30
-
I want to compare two floating point numbers to determine if they are equal to a precision that is close to but not equal to the precision of the representation. I'm interested in doing this in Python. See the AlmostEqual2sComplement function at http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm - I know I can do that with things like (a-b)/a < delta, but am interested in how to do this 'properly' as described at the previous link. – astrofrog Aug 27 '10 at 20:38
4 Answers
AFAIK, IEEE754 floats have an interesting property. If you have float f, then
(*(int*)&f + 1)
under certain conditions, is the next representable floating point number. So for floats a and b
*(int*)&a - *(int*)&b
Will give you the amount of floating point numbers between those numbers.
See http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm for more information.

- 55,122
- 7
- 121
- 140
-
6The only requirement is that they have the same sign, and neither is Nan or inf. – Chris Dodd Aug 27 '10 at 20:50
-
1Looks like it's *the* answer to the question, but one part is missing: how does one do that in Python? – Bolo Aug 27 '10 at 20:56
-
While this does not answer the question for Python, this is a very good answer. My textbook on "Computational Methods" agrees with this as well. Anyone know of a way to convert this to Python? – Dragontamer5788 Aug 27 '10 at 20:59
-
@Dragontamer5788 In the meantime I noticed @jsbueno's answer which utilizes struct.pack/unpack in order to do that conversion. – Bolo Aug 27 '10 at 21:06
-
I believe http://stackoverflow.com/questions/5415/convert-bytes-to-floating-point-numbers-in-python will help convert the code to python. – Dr. Snoopy Aug 27 '10 at 21:06
-
This conversion is what I am doing with the python struct module on my answer. I pack doubles and unpack long ints. – jsbueno Aug 27 '10 at 21:10
-
I don'tknow what you will be using this for - but, if both floats have the same exponent, it should be possible. As the exponent is kept on the high order bits, loading the float bytes (8 bytes in this case) as an integer and subtracting one from another should give the number you want. I use the struct model to pack the floats to a binary representation, and then unpack those as (C, 8 byte) long ints:
>>> import struct
>>> a = struct.pack("dd", 1.000000,1.000001)
>>> b = struct.unpack("ll",a)
>>> b[1] - b[0]
4503599627
>>> a = struct.pack("dd", 1.000000000,1.000000001)
>>> b = struct.unpack("ll",a)
>>> b[1] - b[0]
4503600
>>>

- 99,910
- 10
- 151
- 209
-
-
3+1; nice answer. It's not going to work on systems with a 32-bit C long, though. To be on the safe side, use " – Mark Dickinson Aug 28 '10 at 16:46
-
To be complete, you might also mention that this solution only works for IEEE 754 formats. In practice, that's not much of a restriction, though---it's very difficult to find Python running on a platform using non IEEE 754 doubles. – Mark Dickinson Aug 28 '10 at 16:49
For positive numbers b > a > 0, the answer is approximately:
(2**52) ** (log(b,2) - log(a,2))
There are 52 bits of mantissa ( past the implied 1 ), multiplied by 2 raised to an exponent.
So there are 2**52 numbers in range [1:2) as in the range [1024:2048)

- 8,117
- 4
- 30
- 51
-
The teory is good - but it does not work for me when the float numbers are too close. Possibly due to the fact that the log calculation introduces some rounding itself. – jsbueno Aug 27 '10 at 21:07
I would look at the frexp function in the math module. The example below extracts the mantissa and converts it to an integer. The difference should be the number of floats between to the two values.
>>> math.frexp(1.1234567890)[0] * 2**53
5059599576307254.0
>>> math.frexp(1.12345678901)[0] * 2**53
5059599576352290.0
The following code should do it:
import math
import sys
def delta(x,y):
'''Return the number of floats between x and y.'''
x = float(x)
y = float(y)
if x == y:
return 0
elif x < y:
return -delta(y,x)
else:
x_mant, x_exp = math.frexp(x)
y_mant, y_exp = math.frexp(y)
x_int = int(x_mant * 2**(sys.float_info.mant_dig + x_exp - y_exp))
y_int = int(y_mant * 2**sys.float_info.mant_dig)
return x_int - y_int
print(delta(1.123456789, 1.1234567889999))
450
>>>

- 11,093
- 1
- 24
- 35