继续Difference between Python float and 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的docs评论的那样:
%格式化运算符要求将其参数转换为标准python类型
和
print(repr(float(float_32)))
打印
58682.7578125
@MarkDickinson here给出了一个有趣的见解,显然repr
应该是忠实的(然后他说这对np.float32
不忠实。)
因此,请允许我重申我的问题如下:
float_32
和a
的确切内部表示?如果这些是相同的,那么问题就解决了,如果没有,float
和np.float32
之间进行比较时,向上/向下转换的具体规则是什么?虽然@WillemVanOnsem建议in the comments反之亦然,但我猜它会将float_32向上移动浮动我的python版本:
Python 3.5.2(v3.5.2:4def2a2901a5,2016年6月25日,22:18:55)[MSC v.1900 64 bit(AMD64)] on win32
答案 0 :(得分:4)
数字比较相等,因为58682.7578125可以在32位和64位浮点中精确表示。让我们仔细看看二进制表示:
class Check(models.Model):
name = models.CharField(max_length=100, blank=True)
interval = models.DurationField(default=td(hours=1))
last_run = models.DateTimeField(null=True, blank=True)
def run_function(self):
return HttpResponse("....")
它们具有相同的符号,相同的指数和相同的分数 - 64位表示中的额外位用零填充。
无论他们演出哪种方式,他们都会比较平等。如果您尝试使用其他数字,例如58682.757812 4 ,您会看到二进制级别的表示形式不同; 32位失去了更高的精度,它们不会相等。
(在二进制表示中也很容易看到float32可以向上传播到float64而不会丢失任何信息。这就是numpy在比较两者之前应该做的事情。)
32 bit: 01000111011001010011101011000010
sign : 0
exponent: 10001110
fraction: 11001010011101011000010
64 bit: 0100000011101100101001110101100001000000000000000000000000000000
sign : 0
exponent: 10000001110
fraction: 1100101001110101100001000000000000000000000000000000
答案 1 :(得分:2)
内部存储相同的值,但不会显示print
尝试:
print "%0.8f" % float_32
答案 2 :(得分:2)
十进制58682.7578125是确切的分数(7511393/128
)。
分母是2(2**7
)的幂,分子跨度为23位。因此,这个十进制值可以在float32(有24位有效位)和float64。
因此,Victor T的答案是正确的:在内部表示中,它是相同的值。
对于相同的值,即使对于不同的类型,平等回答都是真的这一事实是IMO的一件好事,您对(2 == 2.0)
有什么期望?
答案 3 :(得分:2)
他们是平等的。他们只是不打印相同的,因为他们使用不同的打印逻辑。
如何在示例中获得float_32和a的确切内部表示?
嗯,这取决于你的意思&#34;确切的内部表示&#34;。如果你真的想要一个比特值,你可以得到一个比特值数组:
>>> 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)
尽可能接近&#34;确切的内部表示&#34;,但它并不是最有用的东西。 (此外,结果将依赖于字节顺序,因为它实际上基于原始内部表示。)
如果你想要一个C级浮点数,这就是NumPy在C级表示float32值的方式......那么,那就是C.除非你想编写自己的C扩展模块,否则你可以&#39; t直接使用C级值。你能得到的最接近的是C浮子周围的某种包装,嘿!你已经有一个!但是,你似乎并不满意,所以这并不是你想要的。
如果你想要用人类可读的十进制表示的精确值,使用str.format
或者将它转换为常规浮点数然后decimal.Decimal
就可以做到这一点,就可以打印它。{/ p >
>>> b
58682.758
>>> decimal.Decimal(float(b))
Decimal('58682.7578125')
您选择的58682.7578125值恰好可以表示为浮点数,因此出现的十进制表示恰好是您输入的值,但通常情况并非如此。您输入的确切十进制表示将被丢弃且无法恢复。
在python&lt; float和np.float32之间进行比较时,向上/向下转换的确切规则是什么?
float32无损地转换为float64。
答案 4 :(得分:0)
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中与这个具体值相同(这是故意吗?)但它可能与其他值不同。