识别并避免舍入错误

当用数字逼近一个值时,请记住浮点结果可能对所使用的精度很敏感。而且,浮点结果很容易出现舍入错误。以下方法可以帮助您识别和避免错误的结果。

尽可能使用符号计算

表演象征性的计算,因为精确的符号计算不容易出现舍入错误。例如,标准数学常量在symbolic Math Toolbox™中有自己的符号表示:

pi-sym(pi)
ans=3.1416 ans=pi

避免不必要地使用数值近似值。浮点数近似于常数,而不是常数本身。使用此近似值,可能会得到不正确的结果。例如重熔特殊函数为正弦函数返回不同的结果符号(pi)和数值逼近的正弦π:

海威西德(sin(sym(pi))海威西德(sin(pi))
ans=1/2 ans=1

以更高的精度执行计算

Riemann假设表明Riemann Zeta函数的所有非平凡零ζ(Z)实部相同吗ℜ(Z) = 1/2。要定位Zeta函数的可能零点,请绘制其绝对值|ζ(1/2 +艾伊)|. 下图显示了Zeta函数的前三个非平凡根|ζ(1/2 +艾伊)|

符号Yfplot(abs(zeta(1/2+i*y)),[0 30])

使用数值求解器vpasolve要近似此Zeta函数的前三个零:

vpasolve(zeta(1/2+i*y),y,15)vpasolve(zeta(1/2+i*y),y,20)vpasolve(zeta(1/2+i*y),y,25)
ans=14.134725141734693790457251983562 ans=21.022039638771554992628479593897 ans=25.01085758014568876321379092563

现在,考虑同样的函数,稍微增加实部, ζ ( 1000000001 2000000000 + Y ) .根据黎曼假设,这个函数对于任何实值都不为零Y.如果你使用vpasolve对于10个有效十进制数字,解算器将查找Zeta函数的以下(不存在)零:

old=数字;数字(10)vpasolve(zeta(1000000001/2000000+i*y),y,15)
ans=14.13472514

增加位数表示结果不正确。Zeta函数 ζ ( 1000000001 2000000000 + Y ) 没有任何实际值的零14 <Y< 15:

数字(15)vpasolve(zeta(1000000001/2000000+i*y),y,15)位(旧)
ans=14.1347251417347+0.000000000499989207306345i

对于进一步的计算,请恢复默认的位数:

数字(旧)

比较符号和数字结果

具有半整数索引的贝塞尔函数返回精确的符号表达式。用浮点数近似这些表达式可能会产生非常不稳定的结果。例如,以下贝塞尔函数的精确符号表达式为:

B=besselj(53/2,符号(pi))
B = (351*2^(1/2)*(119409675/pi^4 - 20300/pi^2 - 315241542000/pi^6…+ 4454757038750 /pi^8 - 366812794263762000/pi^10 +…182947881139051297500 /π^ 12 - 182947881139051297500 /π^ 14…+ 1017414868369239020903125 /pi^16 - 1060253389142977540073062500/pi^18…+ pi^20 - 1331871030107060331702688875000/pi^22…+ 8490677816932509614604641578125/ ^24 + 1) / ^2

使用vpa要以10位精度近似此表达式,请执行以下操作:

vpa(B,10)
ans=-2854.225191

现在,使用浮点参数调用贝塞尔函数。这两个近似值之间的显著差异表明一个或两个结果不正确:

贝塞尔(53/2,pi)
ans=6.9001e-23

提高数值工作精度,以获得更精确的近似值B:

vpa(B,50)
ans = 0.000000000000000000000069001456069172842068862232841396473796597233761161

绘制函数或表达式

绘制结果有助于识别错误的近似值。例如,以下贝塞尔函数的数值近似值返回:

B=besselj(53/2,sym(pi));vpa(B,10)
ans=-2854.225191

绘制此贝塞尔函数的值x周围53/2.函数图表明近似是错误的:

符号xfplot(besselj(x,sym(pi)),[26 27])