2010-08-27 82 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 
>>>