Advice: Roundoff error

"Real" numbers are generally represented in computers using floating-point arithmetic, which is similar to so-called "scientific notation". While most computers use a base-2 system in their "hardware floats", Maple uses base 10. Thus a nonzero floating-point number could be represented in the form (+ or -) r*10^k where [Maple Math] , the exponent, is an integer and [Maple Math] , the mantissa, is in the interval [Maple Math] and has some number [Maple Math] of decimal digits. Actually Maple's internal representation of the number is Float(a,b) where [Maple Math] and [Maple Math] are integers. If the number is produced by floating-point arithmetic, then [Maple Math] is at most the value of the environment variable Digits at that time.

Roundoff error is caused by the fact that numbers are generally not representable exactly with Digits digits, and thus must be approximated by numbers that are represented in this way. The procedure that is used, known as rounding, determines the closest number that can be represented. In particular, the result of an arithmetic operation on floating-point numbers generally requires rounding. Suppose, for example, you were using Digits=4 , and you wanted to multiply [Maple Math] (represented to 4 digits as .3142*10^1 ) by 76.54 ( .7654*10^2 ). You calculate .3142*.7654=.24048868 , and round this to the four-digit number .2405 . Thus the result, after taking care of the powers of 10, is 240.5 ( .2405*10^3 ).

> Digits:= 4: evalf(Pi*76.54);

[Maple Math]

Maple's built-in functions are also subject to roundoff error when they operate on floating-point numbers. In most cases what is computed is an approximation to the function (using a few more digits than Digits), and then the result is rounded. This usually results in the correct rounded value of the function, but once in a while it may be off by a digit or two. In the example below, the correct value with Digits=14 would end in 27, but the computed value ends in 31.

> x := 1.5707963267949:
evalf(tan(x),14);

[Maple Math]

> evalf(tan(x),20); evalf(",14);

[Maple Math]

[Maple Math]

The error in a calculation can be measured in two ways: the absolute error is the magnitude of the difference between the true value and the approximation, while the relative error is the absolute error divided by the magnitude of the true value. In many cases, the relative error is the more useful (of course, it is not much use when the true value is 0).

Multiplication and division do not cause too many problems of accuracy, because they have little effect on relative error. For addition and subtraction, on the other hand, there are two important problems to note.

The first is that when two numbers of very different magnitudes are added, many of the digits of the smaller one will have no effect on the result. This means that calculating a sum of very many, very small quantities can lead to very inaccurate results.

> Digits:= 4: add(4./9000,i=1..900);

[Maple Math]

The correct result, of course, would be [Maple Math] . But when the total gets to .1, each addition of 4./9000 = .000444... with Digits = 4 has only the effect of adding .0004. Even more strikingly, when the total gets to 1, further additions have no effect at all.

> add(4./9000,i=1..9000);

[Maple Math]

The second problem is that subtraction of two nearly equal quantities will result in a large relative error. For example,still with Digits = 4 :

> 4.322-4.321;

[Maple Math]

This in itself is a completely correct calculation, with no roundoff. But if one or both of the numbers 4.322 and 4.321 are approximations for other numbers, the relative error in the difference may be very large. For example, the true values might be 4.3216 and 4.3214 respectively, so the true difference is .0002, for a huge relative error of 4. One place where this can cause unexpected problems is in the standard formula for solving a quadratic equation:
[Maple Math]

Suppose [Maple Math] is positive, and large compared to [Maple Math] and [Maple Math] . Then [Maple Math] will be nearly [Maple Math] . Although it's fine for [Maple Math] , the formula can produce a relatively very inaccurate [Maple Math] . We'll try it for [Maple Math] [Maple Math] and [Maple Math] with Digits = 10 .

> Digits:= 10:
r[`-`]:= b -> (-b - sqrt(b^2-4))/2:
r[`+`]:= b -> (-b + sqrt(b^2-4))/2:
blist:= [130., 13000., 1300000.]:

Here are the results for [Maple Math] at these [Maple Math] values:

> map(r[`-`],blist);

[Maple Math]

Using fsolve with Digits = 20 confirms that these are accurate to nearly 10 digits (the final digits of [Maple Math] and [Maple Math] are off by 1).

> Digits:= 20: map(b -> min(fsolve(x^2+b*x+1,x)),blist);
Digits:= 10:

[Maple Math]

However, the [Maple Math] results are much poorer in relative accuracy.

> map(r[`+`],blist);

[Maple Math]

According to fsolve , we have five correct digits for [Maple Math] , one for [Maple Math] and none for [Maple Math] .

> Digits:= 20: map(b -> max(fsolve(x^2+b*x+1,x)),blist);
Digits:= 10:

[Maple Math]

A better formula for [Maple Math] in this case exploits the fact that the product of the two roots is 1.

> s:= unapply(normal(1/r[`-`](b)),b);

[Maple Math]

> map(s,blist);

[Maple Math]

There is no subtraction of nearly equal quantities here, and the results have 10, 9 and 10 correct digits respectively.

See also: Automatic simplification and evalf , Digits , evalf , Exact vs. floating-point computations , Forcing floating-point arithmetic , The meaning of Digits

Maple Advisor Database, R. Israel 1997