为何部分Numpy数值并非整数?两类计算场景的疑问咨询
嘿,这个问题本质上是计算机浮点数的二进制存储与计算特性导致的,和Numpy本身关系不大——换成普通Python浮点数也会遇到类似情况,咱们一个个拆解:
场景1:np.sqrt(2.)**2得到2.0000000000000004而不是2
首先,√2是个无理数,它的十进制是无限不循环的,转换成二进制也是无限循环的。但计算机里的浮点数(比如Python的float,对应Numpy的float64)只能用固定位数的二进制存储,只能存下它的近似值,没法完美表示真实的√2。
当你计算np.sqrt(2.)时,得到的就是这个近似的二进制浮点数,它和真实值之间有极其微小的误差。把这个近似值平方后,误差被放大,就出现了2.0000000000000004——这其实是计算机能表示的最接近整数2的浮点数。
你甚至不用Numpy,普通Python代码跑出来结果也一样:
print((2.0 ** 0.5) ** 2) # 输出同样是2.0000000000000004
场景2:np.linspace(0, 10, 10)生成的多数是小数
np.linspace(start, stop, num)的核心逻辑是生成num个均匀分布在[start, stop]之间的数,每个数的计算公式是:start + i * (stop - start) / (num - 1),其中i从0到num-1。
在你的例子里,(stop - start)/(num - 1) = 10/9 ≈ 1.1111111111111112,这个值是无限循环的二进制小数,同样没法被浮点数精确存储。所以除了首尾的0和10(这俩是整数,能被精确表示),中间的每个数都是i * 10/9的近似值,自然就呈现出带多位小数的形式。
你手动算一下1*10/9、2*10/9这些值也能发现,它们本身就是无限循环的十进制小数,计算机用二进制浮点数存储时只能保留有限位,最终就出现了你看到的结果。
内容的提问来源于stack exchange,提问作者Anonymous RU

