Mr_*_*s_D 4 python floating-point numpy python-3.x
继续从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)
Run Code Online (Sandbox Code Playgroud)
印刷品:
<class 'float'> 58682.7578125
<class 'numpy.float32'> 58682.8
True
Run Code Online (Sandbox Code Playgroud)
我完全理解,比较浮点数是否相等不是一个好主意,但还是不应该为False(我们在谈论的是第一个十进制数字的差异,而不是0.000000001)?是否依赖系统?是否在某处记录了这种行为?
编辑:好吧,这是第三位小数:
print(repr(float_32), repr(a))
# 58682.758 58682.7578125
Run Code Online (Sandbox Code Playgroud)
但是我可以相信repr吗?那些如何最终存储在内部?
EDIT2:人们坚持以更高的精度打印float_32会给我它的表示形式。但是,正如我已经根据nympy的文档评论的那样:
%格式运算符要求将其参数转换为标准python类型
和:
print(repr(float(float_32)))
Run Code Online (Sandbox Code Playgroud)
版画
58682.7578125
@MarkDickinson 在这里给出了一个有趣的见解,显然repr应该是忠实的(然后他说这是不忠实的np.float32)。
因此,让我重申如下问题:
float_32afloat和之间进行比较时,上/下转换的确切规则是什么np.float32?我猜想它会将float_32转换为float,尽管@WillemVanOnsem 在评论中建议相反我的python版本:
在Win32上的Python 3.5.2(v3.5.2:4def2a2901a5,Jun 25 2016,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
Run Code Online (Sandbox Code Playgroud)
它们具有相同的符号,相同的指数和相同的分数-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:])
Run Code Online (Sandbox Code Playgroud)