2010-08-27 80 views
10

间数花车说我有两个Python漂浮ab,有一个简单的方法来找出表示的实数有多少是两个IEEE-754表示之间(或任何表示所使用的打印机是使用)?两个浮点数

+1

只是出于好奇,你有什么需要这些信息的呢? – 2010-08-27 20:30:29

+0

你是什么意思?两个特定的花车或一般?你想能够从Python做到这一点,或者你想手动进行计算吗? – terminus 2010-08-27 20:30:52

+0

我想比较两个浮点数,以确定它们是否等于接近但不等于表示精度的精度。我对使用Python做这件事很感兴趣。请参阅http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm上的AlmostEqual2sComplement函数 - 我知道我可以用(ab)/ a astrofrog 2010-08-27 20:38:44

回答

10

我don'tknow你会使用什么本作 - 但是,如果同时有花车相同的指数,它应该是可能的。由于指数保持在高位,因此将浮点字节(在本例中为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 
>>> 
+0

结果指数并不重要,但标志确实如此。 – 2010-08-27 20:51:43

+3

+1;很好的答案。不过,它不适用于长32位C的系统。为了安全起见,使用“ 2010-08-28 16:46:23

+0

要完整,您可能还会提到此解决方案仅适用于IEEE 754格式。实际上,这并不是什么限制,但是 - 在使用非IEEE 754双打的平台上运行Python是非常困难的。 – 2010-08-28 16:49:12

3

对于正数B> A> 0,答案是大约

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

有尾数的52位(过去的隐含1),再乘以2提升到的指数。

因此,有在范围内2 ** 52号[1:2)的范围是[1024:2048)

+0

这个teory很不错 - 但是当浮点数太接近时它不适用于我。可能是由于日志计算引入了一些舍入本身。 – jsbueno 2010-08-27 21:07:42

12

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

(*(int*)&f + 1) 

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

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

会给你这些数字之间的浮点数的数量。

查看http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm了解更多信息。

+6

唯一的要求是它们具有相同的符号,并且既不是南或inf。 – 2010-08-27 20:50:12

+0

看起来它是*问题的答案,但是缺少一部分:如何在Python中做到这一点? – Bolo 2010-08-27 20:56:18

+0

虽然这不能回答Python的问题,但这是一个非常好的答案。我的“计算方法”教科书也同意这一点。 任何人都知道一种方法将其转换为Python? – Dragontamer5788 2010-08-27 20:59:01

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 
>>>