Main Content

Variable-precision arithmetic (arbitrary-precision arithmetic)

**Support for character vectors that do not define a number has been removed. Instead, first
create symbolic numbers and variables using sym and
syms, and then use operations on them. For example, use vpa((1
+ sqrt(sym(5)))/2) instead of vpa('(1 + sqrt(5))/2').**

`vpa(`

uses variable-precision
floating-point arithmetic (VPA) to evaluate each element of the symbolic
input `x`

)`x`

to at least `d`

significant
digits, where `d`

is the value of the `digits`

function.
The default value of `digits`

is 32.

Evaluate symbolic inputs with variable-precision
floating-point arithmetic. By default, `vpa`

calculates
values to 32 significant digits.

syms x p = sym(pi); piVpa = vpa(p)

piVpa = 3.1415926535897932384626433832795

a = sym(1/3); f = a*sin(2*p*x); fVpa = vpa(f)

fVpa = 0.33333333333333333333333333333333*sin(6.283185307179586476925286766559*x)

Evaluate elements of vectors or matrices with variable-precision arithmetic.

V = [x/p a^3]; M = [sin(p) cos(p/5); exp(p*x) x/log(p)]; vpa(V) vpa(M)

ans = [ 0.31830988618379067153776752674503*x, 0.037037037037037037037037037037037] ans = [ 0, 0.80901699437494742410229341718282] [ exp(3.1415926535897932384626433832795*x), 0.87356852683023186835397746476334*x]

**Note**

You must wrap all inner inputs with `vpa`

,
such as `exp(vpa(200))`

. Otherwise the inputs are
automatically converted to double by MATLAB^{®}.

`vpa`

By default, `vpa`

evaluates
inputs to 32 significant digits. You can change the number of significant
digits by using the `digits`

function.

Approximate the expression `100001/10001`

with
seven significant digits using `digits`

. Save the
old value of `digits`

returned by `digits(7)`

.
The `vpa`

function returns only five significant
digits, which can mean the remaining digits are zeros.

digitsOld = digits(7); y = sym(100001)/10001; vpa(y)

ans = 9.9991

Check if the remaining digits are zeros by using a higher precision
value of `25`

. The result shows that the remaining
digits are in fact a repeating decimal.

digits(25) vpa(y)

ans = 9.999100089991000899910009

Alternatively, to override `digits`

for a
single `vpa`

call, change the precision by specifying
the second argument.

Find π to 100 significant digits by specifying the second argument.

vpa(pi,100)

ans = 3.141592653589793238462643383279502884197169... 39937510582097494459230781640628620899862803... 4825342117068

Restore the original precision value in `digitsOld`

for
further calculations.

digits(digitsOld)

While symbolic results are exact, they might
not be in a convenient form. You can use `vpa`

to
numerically approximate exact symbolic results.

Solve a high-degree polynomial for its roots using `solve`

.
The `solve`

function cannot symbolically solve
the high-degree polynomial and represents the roots using `root`

.

syms x y = solve(x^4 - x + 1, x)

y = root(z^4 - z + 1, z, 1) root(z^4 - z + 1, z, 2) root(z^4 - z + 1, z, 3) root(z^4 - z + 1, z, 4)

Use `vpa`

to numerically approximate the
roots.

yVpa = vpa(y)

yVpa = 0.72713608449119683997667565867496 - 0.43001428832971577641651985839602i 0.72713608449119683997667565867496 + 0.43001428832971577641651985839602i - 0.72713608449119683997667565867496 - 0.93409928946052943963903028710582i - 0.72713608449119683997667565867496 + 0.93409928946052943963903028710582i

`vpa`

Uses Guard Digits to Maintain PrecisionThe value of the `digits`

function
specifies the minimum number of significant digits used. Internally, `vpa`

can
use more digits than `digits`

specifies. These
additional digits are called guard digits because they guard against
round-off errors in subsequent calculations.

Numerically approximate `1/3`

using four significant
digits.

a = vpa(1/3, 4)

a = 0.3333

Approximate the result `a`

using 20 digits.
The result shows that the toolbox internally used more than four digits
when computing `a`

. The last digits in the result
are incorrect because of the round-off error.

vpa(a, 20)

ans = 0.33333333333303016843

Hidden round-off errors can cause unexpected results.

Evaluate `1/10`

with the default 32-digit precision,
and then with the 10 digits precision.

a = vpa(1/10, 32) b = vpa(1/10, 10)

a = 0.1 b = 0.1

Superficially, `a`

and `b`

look
equal. Check their equality by finding `a - b`

.

a - b

ans = 0.000000000000000000086736173798840354720600815844403

The difference is not equal to zero because `b`

was
calculated with only `10`

digits of precision and
contains a larger round-off error than `a`

. When
you find `a - b`

, `vpa`

approximates `b`

with
32 digits. Demonstrate this behavior.

a - vpa(b, 32)

ans = 0.000000000000000000086736173798840354720600815844403

`vpa`

Restores Precision of Common Double-Precision InputsUnlike exact symbolic values, double-precision
values inherently contain round-off errors. When you call `vpa`

on
a double-precision input, `vpa`

cannot restore
the lost precision, even though it returns more digits than the double-precision
value. However, `vpa`

can recognize and restore
the precision of expressions of the form *p*/*q*, *p*π/*q*, (*p*/*q*)^{1/2}, 2^{q},
and 10^{q},
where *p* and *q* are modest-sized
integers.

First, demonstrate that `vpa`

cannot restore
precision for a double-precision input. Call `vpa`

on
a double-precision result and the same symbolic result.

dp = log(3); s = log(sym(3)); dpVpa = vpa(dp) sVpa = vpa(s) d = sVpa - dpVpa

dpVpa = 1.0986122886681095600636126619065 sVpa = 1.0986122886681096913952452369225 d = 0.00000000000000013133163257501600766255995767652

As expected, the double-precision result differs from the exact
result at the 16^{th} decimal place.

Demonstrate that `vpa`

restores precision
for expressions of the form *p*/*q*, *p*π/*q*, (*p*/*q*)^{1/2}, 2^{q},
and 10^{q},
where *p* and *q* are modest sized
integers, by finding the difference between the `vpa`

call
on the double-precision result and on the exact symbolic result. The
differences are `0.0`

showing that `vpa`

restores
lost precision in the double-precision input.

vpa(1/3) - vpa(1/sym(3)) vpa(pi) - vpa(sym(pi)) vpa(1/sqrt(2)) - vpa(1/sqrt(sym(2))) vpa(2^66) - vpa(2^sym(66)) vpa(10^25) - vpa(10^sym(25))

ans = 0.0 ans = 0.0 ans = 0.0 ans = 0.0 ans = 0.0

`vpa`

does not convert fractions in the exponent to floating point. For example,`vpa(a^sym(2/5))`

returns`a^(2/5)`

.`vpa`

uses more digits than the number of digits specified by`digits`

. These extra digits guard against round-off errors in subsequent calculations and are called guard digits.When you call

`vpa`

on a numeric input, such as`1/3`

,`2^(-5)`

, or`sin(pi/4)`

, the numeric expression is evaluated to a double-precision number that contains round-off errors. Then,`vpa`

is called on that double-precision number. For accurate results, convert numeric expressions to symbolic expressions with`sym`

. For example, to approximate`exp(1)`

, use`vpa(exp(sym(1)))`

.If the second argument

`d`

is not an integer,`vpa`

rounds it to the nearest integer with`round`

.`vpa`

restores precision for numeric inputs that match the forms*p*/*q*,*p*π/*q*, (*p*/*q*)^{1/2}, 2^{q}, and 10^{q}, where*p*and*q*are modest-sized integers.Atomic operations using variable-precision arithmetic round to nearest.

The differences between variable-precision arithmetic and IEEE Floating-Point Standard 754 are

Inside computations, division by zero throws an error.

The exponent range is larger than in any predefined IEEE mode.

`vpa`

underflows below approximately`10^(-323228496)`

.Denormalized numbers are not implemented.

Zeroes are not signed.

The number of

*binary*digits in the mantissa of a result may differ between variable-precision arithmetic and IEEE predefined types.There is only one

`NaN`

representation. No distinction is made between quiet and signaling`NaN`

.No floating-point number exceptions are available.

`digits`

| `double`

| `root`

| `vpaintegral`