12

假设我有两个 Python 浮点数ab是否有一种简单的方法可以找出 IEEE-754 表示(或机器使用的任何表示)中两者之间有多少可表示的实数?

4

4 回答 4

13

AFAIK,IEEE754 浮点数有一个有趣的特性。如果你有float f,那么

(*(int*)&f + 1)

在某些条件下,是下一个可表示的浮点数。所以对于浮动 a 和 b

*(int*)&a - *(int*)&b

将为您提供这些数字之间的浮点数。

有关详细信息,请参阅http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

于 2010-08-27T20:45:29.180 回答
12

我不知道您将使用它来做什么-但是,如果两个浮点数具有相同的指数,那应该是可能的。由于指数保持在高位,因此将浮点字节(在本例中为 8 个字节)加载为整数并从另一个字节中减去一个应该给出您想要的数字。我使用结构模型将浮点数打包为二进制表示,然后将它们解压缩为 (C, 8 字节) 长整数:

>>> 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
>>>
于 2010-08-27T20:43:15.023 回答
3

对于正数 b > a > 0,答案大约是:

(2**52) ** (log(b,2) - log(a,2))

尾数有 52 位(超过隐含的 1 ),乘以 2 得到一个指数。

所以在 [1:2) 范围内有 2**52 个数字,在 [1024:2048) 范围内

于 2010-08-27T20:38:40.237 回答
0

我会查看数学模块中的 frexp 函数。下面的示例提取尾数并将其转换为整数。差异应该是两个值之间的浮点数。

>>> math.frexp(1.1234567890)[0] * 2**53
5059599576307254.0
>>> math.frexp(1.12345678901)[0] * 2**53
5059599576352290.0

下面的代码应该做到这一点:

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
>>>
于 2010-08-27T23:49:34.913 回答