第一个错误是这样的:
你应该将求和行更改为
array_sum += float(array[i, j])
对于 float64 来说这不会造成问题,对于其他值来说这是一个问题,解释如下。
首先:在进行浮点运算时,您应该始终记住,由于舍入误差而存在小错误。最简单的查看方法是在 python shell 中:
>>> .1+.1+.1-.3
5.551115123125783e-17
但你如何考虑这些错误呢?
当将 n 个正整数相加为总和时,分析相当简单,规则是:
错误(tot)
其中因子 n 通常是总体高估,而机器 epsilon 取决于浮点数的类型(表示大小)。
并且大约是:
float64: 2*10^-16
float32: 1*10^-7
float16: 1*10^-3
人们通常认为误差大约在 tot*machine_epsilon 的合理因子内。
对于我对 float16 的测试,我们得到(总是 +-40000 个变量,总和为 +- 20000):
error(float64) = 3*10^-10 ≈ 80* 20000 * 2*10^-16
error(float32) = 1*10^-1 ≈ 50* 20000 * 1*10^-7
这是可以接受的。
然后浮点数 16 还有另一个问题。有机器 epsilon = 1e-4,你可以看到问题
>>> ar = torch.ones([1], dtype=float16)
>>> ar
tensor([2048.], dtype=torch.float16)
>>> ar[0] += .5
>>> ar
tensor([2048.], dtype=torch.float16)
这里的问题是,当达到值 2048 时,该值不够精确,无法添加 1 或更少的值。更具体地说:使用 float16,您可以“表示”值 2048,也可以表示值 2050,但不能表示介于两者之间的值,因为对于该精度来说,它的位数太少。通过将总和保存在 float64 变量中,您可以解决这个问题。解决这个问题我们得到了 float16:
error(float16) = 16 ≈ 8* 20000 * 1*10^-4
虽然很大,但作为相对于 float16 表示的 20000 的值是可以接受的。
如果您问自己,这两种方法中哪一种是“正确的”,那么答案不是这两种方法,它们都是具有相同精度的近似值,但误差不同。
但正如您可能猜到的那样,使用 sum() 方法更快、更好、更可靠。