vpa

Variable-precision arithmetic (arbitrary-precision arithmetic)

Syntax

``xVpa = vpa(x)``
``xVpa = vpa(x,d)``

Description

example

````xVpa = vpa(x)` uses variable-precision arithmetic (arbitrary-precision floating-point numbers) to evaluate each element of the symbolic input `x` to at least `d` significant digits, where `d` is the value of the `digits` function. The default value of `digits` is 32.```

example

````xVpa = vpa(x,d)` uses at least `d` significant digits instead of the value of `digits`.```

Examples

collapse all

Evaluate symbolic inputs with variable-precision floating-point arithmetic. By default, `vpa` calculates values to 32 significant digits.

```p = sym(pi); pVpa = vpa(p)```
`pVpa = $3.1415926535897932384626433832795$`
```syms x a = sym(1/3); f = a*sin(2*p*x); fVpa = vpa(f)```
`fVpa = $0.33333333333333333333333333333333 \mathrm{sin}\left(6.283185307179586476925286766559 x\right)$`

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

```V = [x/p a^3]; VVpa = vpa(V)```
`VVpa = $\left(\begin{array}{cc}0.31830988618379067153776752674503 x& 0.037037037037037037037037037037037\end{array}\right)$`
```M = [sin(p) cos(p/5); exp(p*x) x/log(p)]; MVpa = vpa(M)```
```MVpa =  $\left(\begin{array}{cc}0& 0.80901699437494742410229341718282\\ {\mathrm{e}}^{3.1415926535897932384626433832795 x}& 0.87356852683023186835397746476334 x\end{array}\right)$```

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; yVpa = vpa(y)```
`yVpa = $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 zeros that are part of a repeating decimal.

```digits(25) yVpa = vpa(y)```
`yVpa = $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.

`pVpa = vpa(pi,100)`
`pVpa = $3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117068$`

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 =  $\left(\begin{array}{c}\mathrm{root}\left({z}^{4}-z+1,z,1\right)\\ \mathrm{root}\left({z}^{4}-z+1,z,2\right)\\ \mathrm{root}\left({z}^{4}-z+1,z,3\right)\\ \mathrm{root}\left({z}^{4}-z+1,z,4\right)\end{array}\right)$```

Use `vpa` to numerically approximate the roots.

`yVpa = vpa(y)`
```yVpa =  $\left(\begin{array}{c}0.72713608449119683997667565867496-0.43001428832971577641651985839602 \mathrm{i}\\ 0.72713608449119683997667565867496+0.43001428832971577641651985839602 \mathrm{i}\\ -0.72713608449119683997667565867496-0.93409928946052943963903028710582 \mathrm{i}\\ -0.72713608449119683997667565867496+0.93409928946052943963903028710582 \mathrm{i}\end{array}\right)$```

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

`aVpa = vpa(a,20)`
`aVpa = $0.33333333333303016843$`

Hidden round-off errors can cause unexpected results.

Evaluate `1/10` with the default 32-digit precision and then with the 10-digit precision.

`a = vpa(1/10,32)`
`a = $0.1$`
`b = vpa(1/10,10)`
`b = $0.1$`

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

`roundoff = a - b`
`roundoff = $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.

`roundoff = a - vpa(b,32)`
`roundoff = $0.000000000000000000086736173798840354720600815844403$`

Unlike 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 $\frac{\mathit{p}}{\mathit{q}}$, $\frac{\mathit{p}\pi }{\mathit{q}}$, ${\left(\frac{\mathit{p}}{\mathit{q}}\right)}^{\frac{1}{2}}$, ${2}^{\mathit{q}}$, and ${10}^{\mathit{q}}$, where $\mathit{p}$ and $\mathit{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)```
`dpVpa = $1.0986122886681095600636126619065$`
`sVpa = vpa(s)`
`sVpa = $1.0986122886681096913952452369225$`
`d = sVpa - dpVpa`
`d = $0.00000000000000013133163257501600766255995767652$`

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

Demonstrate that `vpa` restores precision for expressions of the form $\frac{\mathit{p}}{\mathit{q}}$, $\frac{\mathit{p}\pi }{\mathit{q}}$, ${\left(\frac{\mathit{p}}{\mathit{q}}\right)}^{\frac{1}{2}}$, ${2}^{\mathit{q}}$, and ${10}^{\mathit{q}}$, where $\mathit{p}$ and $\mathit{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 for the double-precision input.

`d = vpa(1/3) - vpa(1/sym(3))`
`d = $0.0$`
`d = vpa(pi) - vpa(sym(pi))`
`d = $0.0$`
`d = vpa(1/sqrt(2)) - vpa(1/sqrt(sym(2)))`
`d = $0.0$`
`d = vpa(2^66) - vpa(2^sym(66))`
`d = $0.0$`
`d = vpa(10^25) - vpa(10^sym(25))`
`d = $0.0$`

Create a symbolic expression `S` that represents $\mathrm{sin}\left(\left[\begin{array}{cc}\pi & \frac{\pi }{2}\\ \frac{\pi }{2}& \frac{\pi }{3}\end{array}\right]\mathbit{X}\right)$, where $\mathbit{X}$ is a 2-by-1 symbolic matrix variable.

```syms X [2 1] matrix S = sin(hilb(2)*pi*X)```
```S =  ```

Evaluate the expression with variable-precision arithmetic.

`SVpa = vpa(S)`
```SVpa =  $\left(\begin{array}{c}\mathrm{sin}\left(3.1415926535897932384626433832795 {X}_{1}+1.5707963267948966192313216916398 {X}_{2}\right)\\ \mathrm{sin}\left(1.5707963267948966192313216916398 {X}_{1}+1.0471975511965977461542144610932 {X}_{2}\right)\end{array}\right)$```

Input Arguments

collapse all

Input to evaluate, specified as a number, vector, matrix, multidimensional array, or a symbolic number, vector, matrix, multidimensional array, expression, function, character vector, or matrix variable.

Number of significant digits, specified as a positive integer scalar. `d` must be greater than 1 and less than ${2}^{29}+1$.

Tips

• `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, 2q, and 10q, where p and q are modest-sized integers.

• Variable-precision arithmetic is different from IEEE® Floating-Point Standard 754 in these ways:

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

• Zeros 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.

Version History

Introduced before R2006a

expand all