提问人:djhoese 提问时间:9/1/2023 更新时间:9/1/2023 访问量:72
Numpy '.astype' 四舍五入
Numpy `.astype` rounding up
问:
类似于 Numpy astype 舍入到错误值,但这似乎是相反的问题,实际上是我想要的(截断)。在我的现实世界中,我正在进行各种计算,其中一些值可能会非常非常接近下一个整数,然后转换为整数。我希望数字被截断,我希望它与操作等效。我最终使用结果作为索引。但是,当我这样做时,它似乎正在四舍五入.这是怎么回事:floor
.astype(np.int32)
In [2]: import numpy as np
...
In [49]: np.array([4319.9997], dtype=np.float32).astype(np.int32)
Out[49]: array([4319], dtype=int32)
In [50]: np.array([4319.9998], dtype=np.float32).astype(np.int32)
Out[50]: array([4320], dtype=int32)
我了解 32 位浮动精度与 64 位浮动精度,但我不了解这里正在做什么的内部操作。astype
答:
重复评论中所说的话。“4319.9997”的 32 位版本实际上更接近“4319.9995”。当 numpy/Python/C 尝试将“4319.9998”从 64 位浮点数转换为 32 位浮点数时,只有两个选项是“4319.9995”或“4320.0”,并且“4320.0”更接近,因此四舍五入。我不能说这完全是这样发生的,但这对我来说是有道理的。
原答案:
我不能说我完全理解我将要回答的问题,但其中一些是有道理的。我认为这归结为 Python(或 C 或其他东西)如何将字符串文字转换为 32 位浮点数。
我从以下位置获取了二进制打印功能:
https://stackoverflow.com/a/16444778/433202
import struct
def binary(num):
return ''.join('{:0>8b}'.format(c) for c in struct.pack('!f', num))
并用它打印出数字作为 32 位 IEEE 浮点数:
In [62]: binary(4319.9997)
Out[62]: '01000101100001101111111111111111'
In [63]: binary(4319.9998)
Out[63]: '01000101100001110000000000000000'
所以符号是 0,指数部分是 10001011,分数有效部分是 000011011111...。
因此,当我输入的那些字符串文字被转换为双精度时,它会达到某个阈值,并且小数部分会加一个 1,从而将所有位汇总到有效数的整数部分。
对我来说,对整个事情的最大误解/误解是,当我被告知将浮点数转换为 int 会“截断”数字的小数部分时,我以为它是在以 10 为基数的中这样做的,但它 (C?) 实际上是在以 2 为基数中这样做的。这显然是有道理的,但在这个问题之前,我从未想过这个问题。
我仍然不明白的部分是为什么我键入“4319.9998”的浮点字符串文字的转换会被提升到下一个数字 (+1)。为什么不接受精度问题并将其保留为与“4319.9997”相同的值?我制作了二进制函数的 64 位(双精度)版本,当我打印出这两个版本的数字时:
In [91]: binary64(4319.9997)
Out[91]: '0100000010110000110111111111111111101100010101101101010111010000'
In [92]: binary64(4319.9998)
Out[92]: '0100000010110000110111111111111111110010111001001000111010001010'
如果您计算位并为 64 位浮点表示形式分开,则这两个值在有效数的“整数”部分之后都有很多 1(在移动过指数位数之后),所以我不确定为什么一个会四舍五入而另一个不会。.
评论
float32
int
array(4319.999, dtype=float32)
.9995
4320.