平均函数不正确的值
Mean function incorrect value
我有一个包含相同条目的 80 元素数组:176.01977965813853
如果我使用均值函数,我将得到值 176.01977965813842
这是为什么?
这是一个最小的工作示例:
using Statistics
arr = fill(176.01977965813853, 80)
julia> mean(arr)
176.01977965813842
我希望这个 return 176.01977965813853
。
这些只是预期的浮点错误。但是如果你需要非常精确的求和,你可以使用更复杂(和昂贵)的求和方案:
julia> using KahanSummation
[ Info: Precompiling KahanSummation [8e2b3108-d4c1-50be-a7a2-16352aec75c3]
julia> sum_kbn(fill(176.01977965813853, 80))/80
176.01977965813853
参考:Wikipedia
我理解的问题可以复现如下:
using Statistics
arr = fill(176.01977965813853, 80)
julia> mean(arr)
176.01977965813842
原因是 julia 默认以 64 位精度执行所有浮点运算(即 Float64
类型)。 Float64
s 不能表示任何实数。每个浮点数之间有一个有限的步长,当您对它们进行算术运算时会产生舍入误差。这些舍入误差通常没什么大碍,但如果您不小心,它们可能会造成灾难性后果。例如:
julia> 1e100 + 1.0 - 1e100
0.0
也就是说,如果我这样做 10^100 + 1 - 10^100
我得到零!如果你想得到由浮点运算引起的误差的上限,我们可以使用 IntervalArithmetic.jl:
using IntervalArithmetic
julia> 1e100 + interval(1.0) - 1e100
[0, 1.94267e+84]
也就是说操作1e100 + 1.0 - 1e100
至少等于0.0
,最多等于1.94*10^84
,所以误差范围很大!
我们可以为您感兴趣的操作做同样的事情,
arr = fill(interval(176.01977965813853), 80);
julia> mean(arr)
[176.019, 176.02]
julia> mean(arr).lo
176.019779658138
julia> mean(arr).hi
176.0197796581391
表示 实际 平均值可能至少 176.019779658138
或最多 176.0197796581391
,但由于浮点数错误!所以在这里,Float64
给出的答案最多有10^-13
%的误差,其实是很小的。
如果这些是不可接受的错误界限怎么办?使用更精确!您可以使用 big
字符串宏来获取任意精度数字文字:
arr = fill(interval(big"176.01977965813853"), 80);
julia> mean(arr).lo
176.0197796581385299999999999999999999999999999999999999999999999999999999999546
julia> mean(arr).hi
176.019779658138530000000000000000000000000000000000000000000000000000000000043
该计算是使用 256 位精度完成的,但您可以使用 setprecision
函数获得更高的精度:
setprecision(1000)
arr = fill(interval(big"176.01977965813853"), 80);
julia> mean(arr).lo
176.019779658138529999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999599
julia> mean(arr).hi
176.019779658138530000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000579
请注意,与 Float64
s 相比,任意精度算法 sloooow,因此通常最好只使用任意精度算法来验证您的结果,以确保您在您想要的精度范围内重新收敛到一个好的结果。
我有一个包含相同条目的 80 元素数组:176.01977965813853
如果我使用均值函数,我将得到值 176.01977965813842
这是为什么?
这是一个最小的工作示例:
using Statistics
arr = fill(176.01977965813853, 80)
julia> mean(arr)
176.01977965813842
我希望这个 return 176.01977965813853
。
这些只是预期的浮点错误。但是如果你需要非常精确的求和,你可以使用更复杂(和昂贵)的求和方案:
julia> using KahanSummation
[ Info: Precompiling KahanSummation [8e2b3108-d4c1-50be-a7a2-16352aec75c3]
julia> sum_kbn(fill(176.01977965813853, 80))/80
176.01977965813853
参考:Wikipedia
我理解的问题可以复现如下:
using Statistics
arr = fill(176.01977965813853, 80)
julia> mean(arr)
176.01977965813842
原因是 julia 默认以 64 位精度执行所有浮点运算(即 Float64
类型)。 Float64
s 不能表示任何实数。每个浮点数之间有一个有限的步长,当您对它们进行算术运算时会产生舍入误差。这些舍入误差通常没什么大碍,但如果您不小心,它们可能会造成灾难性后果。例如:
julia> 1e100 + 1.0 - 1e100
0.0
也就是说,如果我这样做 10^100 + 1 - 10^100
我得到零!如果你想得到由浮点运算引起的误差的上限,我们可以使用 IntervalArithmetic.jl:
using IntervalArithmetic
julia> 1e100 + interval(1.0) - 1e100
[0, 1.94267e+84]
也就是说操作1e100 + 1.0 - 1e100
至少等于0.0
,最多等于1.94*10^84
,所以误差范围很大!
我们可以为您感兴趣的操作做同样的事情,
arr = fill(interval(176.01977965813853), 80);
julia> mean(arr)
[176.019, 176.02]
julia> mean(arr).lo
176.019779658138
julia> mean(arr).hi
176.0197796581391
表示 实际 平均值可能至少 176.019779658138
或最多 176.0197796581391
,但由于浮点数错误!所以在这里,Float64
给出的答案最多有10^-13
%的误差,其实是很小的。
如果这些是不可接受的错误界限怎么办?使用更精确!您可以使用 big
字符串宏来获取任意精度数字文字:
arr = fill(interval(big"176.01977965813853"), 80);
julia> mean(arr).lo
176.0197796581385299999999999999999999999999999999999999999999999999999999999546
julia> mean(arr).hi
176.019779658138530000000000000000000000000000000000000000000000000000000000043
该计算是使用 256 位精度完成的,但您可以使用 setprecision
函数获得更高的精度:
setprecision(1000)
arr = fill(interval(big"176.01977965813853"), 80);
julia> mean(arr).lo
176.019779658138529999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999599
julia> mean(arr).hi
176.019779658138530000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000579
请注意,与 Float64
s 相比,任意精度算法 sloooow,因此通常最好只使用任意精度算法来验证您的结果,以确保您在您想要的精度范围内重新收敛到一个好的结果。