DIGITS

Significant digits of floating-point numbers

MuPAD® notebooks will be removed in a future release. Use MATLAB® live scripts instead.

MATLAB live scripts support most MuPAD functionality, though there are some differences. For more information, see Convert MuPAD Notebooks to MATLAB Live Scripts.

Description

The environment variable DIGITS determines the number of significant decimal digits in floating-point numbers. The default value is DIGITS = 10.

Possible values: a positive integer larger than 1 and smaller than 229 + 1.

Floating point numbers are created by applying the function float to exact numbers or numerical expressions. Elementary objects are approximated by the resulting floats with a relative precision of 10^(-DIGITS), i.e., the first DIGITS decimal digits are correct. See Example 1.

In arithmetical operations with floating-point numbers, only the first DIGITS decimal digits are taken into account. The numerical error propagates and may grow in the course of computations. See Example 2.

If a real floating-point number is entered directly (e.g., by x := 1.234), a number with at least DIGITS internal decimal digits is created.

If a real float is entered with more than DIGITS digits, the internal representation stores the extra digits. However, they are not taken into account in arithmetical operations, unless DIGITS is increased accordingly. See Example 3.

In particular, complex floating-point numbers are created by adding the real and imaginary part. This addition truncates extra decimal places in the real and imaginary part.

The value of DIGITS may be changed at any time during a computation. If DIGITS is decreased, only the leading digits of existing floating numbers are taken into account in the following arithmetical operations. If DIGITS is increased, existing floating-point numbers are internally padded with trailing binary zeroes. See Example 4.

Depending on DIGITS, certain functions such as the trigonometric functions may give wrong results if floats as arguments are too inaccurate. See Example 5.

Depending on DIGITS, only significant digits of floating-point numbers are displayed on the screen. The preferences Pref::floatFormat and Pref::trailingZeroes can be used to modify the screen output. See Example 4.

At least one digit after the decimal point is displayed; if it is insignificant, it is replaced by zero. See Example 6.

Internally, floating-point numbers are created and stored with some extra “guard digits.” These are also taken into account by the basic arithmetical operations.

For example, for DIGITS = 10, the function float converts exact numbers to floats with some more decimal digits. The number of guard digits depends on DIGITS.

At least 2 internal guard digits are available for any value of DIGITS.

See Example 4 and Example 7.

Environment variables such as DIGITS are global variables. Upon return from a procedure that changes DIGITS, the new value is valid outside the context of the procedure as well! Use save DIGITS to restrict the modified value of DIGITS to the procedure. See Example 8.

The default value of DIGITS is 10; DIGITS has this value after starting or resetting the system via reset. Also the command delete DIGITS; restores the default value.

See the helppage of float for further information.

Examples

Example 1

We convert some exact numbers and numerical expressions to floating point approximations:

DIGITS := 10: 
float(PI), float(1/7), float(sqrt(2) + exp(3)), float(exp(-20))

DIGITS := 20:
float(PI), float(1/7), float(sqrt(2) + exp(3)), float(exp(-20))

delete DIGITS:

Example 2

We illustrate error propagation in numerical computations. The following rational number approximates exp(2) to 17 decimal digits:

r := 738905609893065023/100000000000000000:

The following float call converts exp(2) and r to floating point approximations. The approximation errors propagate and are amplified in the following numerical expression:

DIGITS := 6: float(10^20*(r - exp(2)))

None of the digits in this result is correct. A better result is obtained by increasing DIGITS:

DIGITS := 20: float(10^20*(r - exp(2)))

delete r, DIGITS:

Example 3

In the following, only 10 of the entered 30 digits are regarded as significant. The extra digits are stored internally, anyway:

DIGITS := 10:
a := 1.23456789666666666666666666666;
b := 1.23456789444444444444444444444

We increase DIGITS. Because the internal representation of a and b is correct to 30 decimal place, the difference can be computed correctly to 20 decimal places:

DIGITS := 30: a - b

delete a, b, DIGITS:

Example 4

We compute a floating-point number with a precision of 10 digits. Internally, this number is stored with some guard digits. Increasing DIGITS to 30, the correct guard digits become visible. With the the call Pref::trailingZeroes(TRUE), trailing zeroes of the decimal representation become visible:

DIGITS := 10: a := float(1/9)

Pref::trailingZeroes(TRUE): DIGITS := 100: a
0.1111111111111111110147375846679551614215597510337829589843750000000000000000000000000000000000000000
Pref::trailingZeroes(FALSE): delete a, DIGITS:

Example 5

For the float evaluation of the sine function, the argument is reduced to the standard interval [0, 2 π]. For this reduction, the argument must be known to some digits after the decimal point. For small DIGITS, the digits after the decimal point are pure round-off if the argument is a large floating-point number:

DIGITS := 10: sin(float(2*10^30))

Increasing DIGITS to 50, the argument of the the sine function has about 30 correct digits after the decimal point. The first 30 digits of the following result are reliable:

DIGITS := 50: sin(float(2*10^30))

delete DIGITS:

Example 6

At least one digit after the decimal point is always displayed. In the following example, the number 39.9 is displayed as 40.0 because “40.” is not be a valid MuPAD® input:

DIGITS := 2: float(10*PI), 39.9, -30.2

delete DIGITS:

Example 7

We compute float(10^40*8/9) with various values of DIGITS. Rounding takes into account all guard digits, i.e., the resulting integer makes all guard digits visible:

for DIGITS in [7, 8, 9, 17, 18, 19, 26, 27, 28] do
    print("DIGITS" = DIGITS, round(float(10^40*8/9)))
end_for:

Example 8

The following procedure allows to compute numerical approximations with a specified precision without changing DIGITS as a global variable. Internally, DIGITS is set to the desired precision and the float approximation is computed. Because of save DIGITS, the value of DIGITS is not changed outside the procedure:

myfloat := proc(x, digits) 
           save DIGITS;
           begin
             DIGITS := digits:
             float(x);
           end_proc:

The float approximation of the following value x suffers from numerical cancellation. The procedure myloat is used to approximate x with 30 digits. The result is displayed with only 7 digits because of the value DIGITS = 7 valid outside the procedure. However, all displayed digits are correct:

x := PI^7 - exp(8013109200945801/1000000000000000):
DIGITS := 7: 
float(x), myfloat(x, 30)

delete myfloat, x, DIGITS:

Algorithms

If a floating-point number x has been created with high precision, and the computation is to continue at a lower precision, the easiest method to get rid of memory-consuming insignificant digits is x := x + 0.0.