Can you get matlab to add a really small number to a big number and retain precision
Show older comments
I am trying to calculate small numbers from equations like the one below.
p = -1e17 + sqrt(1e34 + 1e18)
I have tried using 'vpa(-1e17 + sqrt(1e34 + 1e18), 30) but the output always comes out as p = 0.0. But p is not exactly zero and this propagates errors in subsequent calculations that involve p. Is there another way to retain sig figs to avoid rounding errors?
2 Comments
Walter Roberson
on 1 May 2026
Open the Neural Net Fitting App
- Before R2026a: MATLAB Toolstrip: On the Apps tab, under Machine Learning and Deep Learning, click the app icon.
- MATLAB command prompt: Enter nftool.
The implication is that it can only be opened from the command line in R2026a.
Walter Roberson
on 2 May 2026
This was posted in response to a comment from FUN-AKEDE about being unable to find the Neural Fitting app in the toolstrip. They have removed the comment since then.
Accepted Answer
More Answers (4)
David Goodmanson
on 18 Apr 2026
Edited: David Goodmanson
on 21 Apr 2026
HI Stephen,
It's certainly doable, but rather than have the software crank away at a precise enough calculation, in this case I think it works better to recognize that a very small parameter is running the show, and sidestep the precision problem all together:
p = -a + sqrt(a^2+b^2) % a = 1e17 b = 1e9 b<<a
= -a + a*sqrt(1 + b^2/a^2)
= -a + a*[1 + (1/2)(b^2/a^2) + ((1/2)(-1/2)/2!)(b^2/a^2)^2 ... ] % series expansion
= -a + a + (1/2)(b^2/a) -(1/8)(b^4/a^3) ...
= (1/2)(1e18/1e17) -(1/8)(1e36/1e51) ...
= 5 - 1.25e-16 ...
which seems accurate enough for most purposes (the next term is +6.25e-33).
1 Comment
John D'Errico
on 18 Apr 2026
A good point, that good numerical analysis can often obviate the need for high precision computations. Well written double precision code will be sufficient for most tasks. I even recall the blog posts from Cleve looking at half precision arithmetic, but there you need to be very careful.
p = sym(-1e17) + sqrt(sym(1e34) + sym(1e18))
vpa(p, 30)
The problem with doing vpa(-1e17 + sqrt(1e34 + 1e18)) is that when you do that, the expression -1e17 + sqrt(1e34 + 1e18) is calculated in double precision, and the double precision result is then converted to symbolic.
In MATLAB, if you use one of the int*() calls or one of the uint*() calls, and inside the () you specify a constant with no complex component, then those int*() or uint*() calls take effect at parse time.
In all other cases, for all other function calls, the parameters are evaluated with default double precision with the function being applied after the resulting expression.
For example
int64(9223372036854775806)
int64(+9223372036854775806)
int64(9223372036854775806.)
The +9223372036854775806 and the 9223372036854775806. are not considered integer literal expressions, so their content is evaluated in double precision, with int64() then applied to the double precision result.
So it is that vpa(-1e17 + sqrt(1e34 + 1e18)) calculates the expression in double precision and applies vpa() to the double precision result.
1 Comment
Walter Roberson
on 17 Apr 2026
Edited: Walter Roberson
on 17 Apr 2026
You have to be careful about how you create the expressions
sym(9223372036854775806)
so as described, if you give a numeric argument to sym() then it is evaluated in default double precision before sym() gets control.
If you quote on the other hand,
sym('9223372036854775806')
but
p1 = sym('-1e17')
p2 = sym('1e34')
p3 = sym('1e18')
p = p1 + sqrt(p2 + p3)
this shows that if you use quoting that the result is a symbolic floating point result, not a symbolic rational.
The fact that parameters get evaluated in default double precision shows that it is unreliable to pass larger or higher precision floating point values. The fact that quoted parameters become symbolic floating point numbers means that you often do not want to pass quoted parameters either.
So it is often better to construct the symbolic numbers, such as
p1 = sym(10)^17
p2 = sym(10)^34
p3 = sym(10)^18
p = p1 + sqrt(p2 + p3)
q = sym(12345)/sym(10)^4
feval(symengine, 'coerce', sym('1e34'), 'DOM_RAT')
Using feval() to coerce a number is decidedly obscure !!!
Can you get matlab to add a really small number to a big number and retain precision
You can, but it is better to just reorganize the computation in a way that doesn't require it.
From the quadratic formula, you can see that p is the right hand root of the quadratic equation,
0.5x^2 + 1e17x - 0.5e18 = 0
It looks like this equation came from a quadratic fit to data that is essentially linear, resulting in small numeric junk for the second degree term. If so, you should just repeat the fit using a linear model only. Or, just disregard the 2nd degree term and solve for the root of the linear part,
1e17x - 0.5e18 = 0
which will then give x=5.
Mathieu NOE
on 6 May 2026
Edited: Mathieu NOE
on 6 May 2026
1 vote
using a first order approximation of the power function f(x) = (1+x)^n
this can be approximated by f1(x) ~= (1+n*x) for x << 1
thus p = -1e17 + sqrt(1e34 + 1e18) can be rewritten :
p = -1e17*(1 - sqrt(1 + 1e18/1e34))
p = -1e17*(1 - sqrt(1 + 1e-16))
p = -1e17*(1 - (1 + 0.5*1e-16))
p = 1e17 * 0.5 * 1e-16 = 5
Categories
Find more on Number Theory in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
