浮点错误从何而来?(使用矩阵乘法与移位和加法的有限差分。)

计算科学 浮点 朱莉娅
2021-12-05 15:14:26

在 Julia 中,使用矩阵乘法与移位和加法进行有限差分时,似乎会发现一些误差项。

julia> n = 1000
1000

julia> hessM = circshift(eye(n),-1) + circshift(eye(n),1) - 2* eye(n);

julia> function hess(x::Vector)
         return circshift(x,-1) + circshift(x,1) - 2*x
       end
hess (generic function with 1 method)

julia> x = rand(n);

julia> maximum(hessM * x - hess(x))
0.0

julia> x = rand(n)/300;

julia> maximum(hessM * x - hess(x))
8.673617379884035e-19

我知道这是浮点错误,因为如果我这样做x = rand(n) / 256(或任何 2 的幂),错误就会消失,但是如果我们除以 3 这样简单的东西,错误就会出现。

但是在运行上述代码时,浮点错误到底在哪里呢?为什么它对划分敏感?


编辑:事实上,我已将差异本地化为

julia> x = rand(n)/3;

julia> maximum(hessM * x + 2 * eye(n) * x - circshift(eye(n),-1) * x - circshift(eye(n),1)*x)
1.1102230246251565e-16

julia> x = rand(n);

julia> maximum(hessM * x + 2 * eye(n) * x - circshift(eye(n),-1) * x - circshift(eye(n),1)*x)
0.0

julia> x = rand(n) * 3;

julia> maximum(hessM * x + 2 * eye(n) * x - circshift(eye(n),-1) * x - circshift(eye(n),1)*x)
8.881784197001252e-16

是什么赋予了?

1个回答

编辑(2021 年 7 月):在 Julia 的 1.7 版本中,作为默认 PRNG 从 Mersenne Twister 移动到 Xoshiro 的副作用,该行为似乎会发生变化。请参阅下面的评论。


这似乎与 Julia 生成随机数的方式有关。我已经在 Julia 语言网站上进行了讨论Julia 的随机数生成器的当前实现[0,1)为浮点的默认范围(换句话说,简单地调用rand())总是产生一个0出于某种原因(例如,与 MATLAB 不同)。这样做的副作用是浮点错误被抑制(因为这些错误通常是来自舍入/取消到最低位的错误)。乘以/除以 2 的幂不会改变浮点表示中的有效位,但是乘以/除以非幂会改变。所以一般来说,在乘以/除以一些非幂之后,最低有效位可以是 1 或零,现在浮点错误就像通常预期的那样发生。