Main Content

Recognize and Avoid Round-Off Errors

When approximating a value numerically, remember that floating-point results can be sensitive to the precision used. Also, floating-point results are prone to round-off errors. The following approaches can help you recognize and avoid incorrect results.

Use Symbolic Computations When Possible

Performing computations symbolically is recommended because exact symbolic computations are not prone to round-off errors. For example, standard mathematical constants have their own symbolic representations in Symbolic Math Toolbox™:

pi
sym(pi)
ans =
    3.1416

ans =
pi

Avoid unnecessary use of numeric approximations. A floating-point number approximates a constant; it is not the constant itself. Using this approximation, you can get incorrect results. For example, the heaviside special function returns different results for the sine of sym(pi) and the sine of the numeric approximation of pi:

heaviside(sin(sym(pi)))
heaviside(sin(pi))
ans =
1/2

ans =
     1

Perform Calculations with Increased Precision

The Riemann hypothesis states that all nontrivial zeros of the Riemann Zeta function ζ(z) have the same real part ℜ(z) = 1/2. To locate possible zeros of the Zeta function, plot its absolute value |ζ(1/2 + iy)|. The following plot shows the first three nontrivial roots of the Zeta function |ζ(1/2 + iy)|.

syms y
fplot(abs(zeta(1/2 + i*y)), [0 30])

Figure contains an axes object. The axes object contains an object of type functionline.

Use the numeric solver vpasolve to approximate the first three zeros of this Zeta function:

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.010857580145688763213790992563

Now, consider the same function, but slightly increase the real part, ζ(10000000012000000000+iy). According to the Riemann hypothesis, this function does not have a zero for any real value y. If you use vpasolve with the 10 significant decimal digits, the solver finds the following (nonexisting) zero of the Zeta function:

old = digits;
digits(10)
vpasolve(zeta(1000000001/2000000000 + i*y), y, 15)
ans =
14.13472514

Increasing the number of digits shows that the result is incorrect. The Zeta function ζ(10000000012000000000+iy) does not have a zero for any real value 14 < y < 15:

digits(15)
vpasolve(zeta(1000000001/2000000000 + i*y), y, 15)
digits(old)
ans =
14.1347251417347 + 0.000000000499989207306345i

For further computations, restore the default number of digits:

digits(old)

Compare Symbolic and Numeric Results

Bessel functions with half-integer indices return exact symbolic expressions. Approximating these expressions by floating-point numbers can produce very unstable results. For example, the exact symbolic expression for the following Bessel function is:

B = besselj(53/2, sym(pi))
B =
(351*2^(1/2)*(119409675/pi^4 - 20300/pi^2 - 315241542000/pi^6...
 + 445475704038750/pi^8 - 366812794263762000/pi^10 +...
 182947881139051297500/pi^12 - 55720697512636766610000/pi^14...
 + 10174148683695239020903125/pi^16 - 1060253389142977540073062500/pi^18...
 + 57306695683177936040949028125/pi^20 - 1331871030107060331702688875000/pi^22...
 + 8490677816932509614604641578125/pi^24 + 1))/pi^2

Use vpa to approximate this expression with the 10-digit accuracy:

vpa(B, 10)
ans =
-2854.225191

Now, call the Bessel function with the floating-point parameter. Significant difference between these two approximations indicates that one or both results are incorrect:

besselj(53/2, pi)
ans =
   6.9001e-23

Increase the numeric working precision to obtain a more accurate approximation for B:

vpa(B, 50)
ans =
0.000000000000000000000069001456069172842068862232841396473796597233761161

Plot the Function or Expression

Plotting the results can help you recognize incorrect approximations. For example, the numeric approximation of the following Bessel function returns:

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

Plot this Bessel function for the values of x around 53/2. The function plot shows that the approximation is incorrect:

syms x
fplot(besselj(x, sym(pi)), [26 27])

Figure contains an axes object. The axes object contains an object of type functionline.