簡體   English   中英

Numpy的float32和float比較

[英]Numpy's float32 and float comparisons

繼續Python float和numpy float32之間的區別

import numpy as np

a = 58682.7578125
print(type(a), a)
float_32 = np.float32(a)
print(type(float_32), float_32)
print(float_32 == a)

打印:

<class 'float'> 58682.7578125
<class 'numpy.float32'> 58682.8
True

我完全明白,將浮點數比較為平等並不是一個好主意但仍然不應該是假的(我們討論的是第一個十進制數字的差異,而不是0.000000001)? 它是系統依賴的嗎? 這種行為是否記錄在案?

編輯:嗯,它是第三個小數:

print(repr(float_32), repr(a))
# 58682.758 58682.7578125

但我可以信任repr嗎? 這些內部存儲在最終結局中的方式如何?

EDIT2:人們堅持認為以更高的精度打印float_32會給我它的代表性。 但是正如我已根據nympy的文檔評論過:

%格式化運算符要求將其參數轉換為標准python類型

和:

print(repr(float(float_32)))

版畫

58682.7578125

一個有趣的見解是@MarkDickinson給出這里 ,顯然repr應該是忠實的(然后他說,這是不是忠實的np.float32 )。

所以讓我重申我的問題如下:

  • 如何在示例中獲得float_32a確切內部表示 如果這些是相同的,那么問題就解決了,如果沒有,
  • 在python的floatnp.float32之間進行比較時,向上/向下轉換的確切規則是什么? 雖然@WillemVanOnsem 在評論中暗示它是另一回事,但我猜它會將float_32向上移動。

我的python版本:

win32上的Python 3.5.2(v3.5.2:4def2a2901a5,2016年6月25日,22:18:55)[MSC v.1900 64位(AMD64)]

數字比較相等,因為58682.7578125可以在32位和64位浮點中精確表示。 讓我們仔細看看二進制表示:

32 bit:  01000111011001010011101011000010
sign    :  0
exponent:  10001110
fraction:  11001010011101011000010

64 bit:  0100000011101100101001110101100001000000000000000000000000000000
sign    :  0
exponent:  10000001110
fraction:  1100101001110101100001000000000000000000000000000000

它們具有相同的符號,相同的指數和相同的分數 - 64位表示中的額外位用零填充。

無論他們演出哪種方式,他們都會比較平等。 如果您嘗試使用其他數字,例如58682.757812 4,您將看到二進制級別的表示不同; 32位失去更高的精度,他們不會比較相等。

(在二進制表示中也很容易看到float32可以向上傳播到float64而不會丟失任何信息。這就是numpy在比較兩者之前應該做的事情。)

import numpy as np

a = 58682.7578125
f32 = np.float32(a)
f64 = np.float64(a)

u32 = np.array(a, dtype=np.float32).view(dtype=np.uint32)
u64 = np.array(a, dtype=np.float64).view(dtype=np.uint64)

b32 = bin(u32)[2:]
b32 = '0' * (32-len(b32)) + b32  # add leading 0s
print('32 bit: ', b32)
print('sign    : ', b32[0])
print('exponent: ', b32[1:9])
print('fraction: ', b32[9:])
print()

b64 = bin(u64)[2:]
b64 = '0' * (64-len(b64)) + b64  # add leading 0s
print('64 bit: ', b64)
print('sign    : ', b64[0])
print('exponent: ', b64[1:12])
print('fraction: ', b64[12:])

內部存儲相同的值,只是它不顯示帶print所有數字

嘗試:

 print "%0.8f" % float_32

請參閱完全精確的相關打印numpy.float64

小數58682.7578125是精確分數( 7511393/128 )。

分母是2( 2**7 )的冪,分子跨度為23位。 所以這個十進制值可以在float32(有24位有效位)和float64中完全表示。

因此,Victor T的答案是正確的:在內部表示中,它是相同的值。

對於相同的值,即使對於不同的類型,平等回答是真的這一事實是IMO的一件好事,你期望什么(2 == 2.0)

他們是平等的。 他們只是不打印相同,因為他們使用不同的打印邏輯。

如何在示例中獲得float_32和a的確切內部表示?

那么,這取決於你所說的“確切的內部表征”。 如果你真的想要一個比特值,你可以得到一個比特值數組:

>>> b = numpy.float32(a)
>>> numpy.unpackbits(numpy.array([b]).view(numpy.uint8))
array([1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0,
       1, 0, 1, 0, 0, 0, 1, 1, 1], dtype=uint8)

這與你的“精確內部表示”一樣接近,但它並不是最有用的東西。 (此外,結果將依賴於字節順序,因為它實際上基於原始內部表示。)

如果你想要一個C級浮點數,這就是NumPy在C級表示float32值的方式......好吧,那就是C.除非你想編寫自己的C擴展模塊,否則你不能直接使用C級值。 你能得到的最接近的是C浮子周圍的某種包裝,嘿! 你已經有一個! 但是你似乎並不滿意,所以這不是你想要的。

如果你想要用人類可讀的十進制表示的確切值,使用str.format以額外的精度打印它,或者將它轉換為常規的float,然后是decimal.Decimal就可以了。

>>> b
58682.758
>>> decimal.Decimal(float(b))
Decimal('58682.7578125')

您選擇的58682.7578125值恰好可以表示為浮點數,因此出現的十進制表示恰好是您放入的值,但通常情況並非如此。 您鍵入的確切十進制表示將被丟棄並且不可恢復。

在python的float和np.float32之間進行比較時,向上/向下轉換的確切規則是什么?

float32無損地轉換為float64。

58682.8

我的機器顯示58682.758這條線。

我完全理解比較花車的平等並不是一個好主意

如果他們獨立計算,那就不是一個好主意。 另一方面,如果您獲得相同的數字並檢查其轉換,這一個好主意。

它是系統依賴的嗎? 這種行為是否記錄在案?

它完全依賴於轉換為文本。 根據評論,float32是必不可少的。 如果是這樣,float32的保證精度是7位十進制數字,不像Python的內部浮點數是float64(至少在x86上)。 這就是為什么該值在打印中被截斷的原因。 以十進制形式打印浮點值的推薦方法是在輸出形式轉換回相同的內部值時停止。 所以它將58682.7578125減少到58682.758:差異小於ULP。

打印為內部“float”或numpy float64的相同值將具有更多有效數字,因為它們的省略將導致另一個內部值:

>>> 58682.758 == 58682.7578125
False
>>> numpy.float32(58682.758) == numpy.float32(58682.7578125)
True
>>> print(repr(numpy.float32(58682.758).data[0:4]))
'\xc2:eG'
>>> print(repr(numpy.float32(58682.7578125).data[0:4]))
'\xc2:eG'
>>> numpy.float64(58682.758) == numpy.float64(58682.7578125)
False
>>> print(numpy.float64(58682.758).hex(), numpy.float64(58682.7578125).hex())
('0x1.ca7584189374cp+15', '0x1.ca75840000000p+15')

你很幸運這兩個值在float32中與這個具體值相同(這是故意嗎?)但它可能與其他值不同。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM