如果两个数字相差太大,最小的数字就会“丢失”。这是否会引发我可以检查的任何标志?
在float32中,有效位有24位二进制数字,因此如果数字之间的差异大于10^7.2,较小的数字将丢失。显然,我可以使用
decimal
或 float64
,但此代码只是一个示例:
# Max 7.2 decimal digits of difference
## First experiment:
np.seterr(all='warn')
n1 = np.pow(np.float32(10), 9)
n2 = np.float32(1)
print("n1:", n1, "n2:", n2, "n1+n2:", n1+n2, "n1+n2==n1:", n1+n2==n1)
# n1: 1000000000.0 n2: 1.0 n1+n2: 1000000000.0 n1+n2==n1: True
## Second experiment
n1 = np.pow(np.float32(10), 9)
total = np.float32(0)
n2 = n1
for i in tqdm(range(10**9)):
total += 1
n2 += 1
print("n1:", n1, "n2:", n2, "total:", total, "n1+total:", n1+total)
# n1: 1000000000.0 n2: 1000000000.0 total: 16777216.0 n1+total: 1016777200.0
是否可以检测是否发生此错误?这种错误怎么称呼以及如何搜索更多信息?
这只是一个舍入误差导致精度损失。
n1+n2
的结果四舍五入为 24 位。
这些情况一直在发生,而不仅仅是加法。无论数字如何,
1/3
都不能表示为二进制数,因此它总是四舍五入。因为它几乎发生在每个操作中,所以尝试检测它的每个实例是不可行的。
相反,通常建议后退一步并使用更好的数值算法,其中舍入误差不会给预期应用带来问题。在这个简单的情况下,解决方案也同样简单:使用整数类型进行整数加法。更复杂的案例有更复杂的解决方案;试图在这里总结这一点是愚蠢的。这个领域称为数值分析,它是数学和计算机科学的结合。