Which is more accurate, x**.5 or math.sqrt(x)?

I recently discovered that x**.5 and math.sqrt(x) do not always produce the same result in Python:

Python 2.6.1 (r261:67517, Dec 4 2008, 16:51:00) [MSC v.1500 32 bit (Intel)]
on win32
>>> 8885558**.5 - math.sqrt(8885558)
-4.5474735088646412e-13

Checking all integers below 10**7, the two methods produced different results for almost exactly 0.1% of the samples, with the size of the error increasing (slowly) for larger numbers.

So the question is, which method is more accurate?


Asked by: Vanessa101 | Posted: 06-12-2021






Answer 1

Neither one is more accurate, they both diverge from the actual answer in equal parts:

>>> (8885558**0.5)**2
8885557.9999999981
>>> sqrt(8885558)**2
8885558.0000000019

>>> 2**1023.99999999999
1.7976931348498497e+308

>>> (sqrt(2**1023.99999999999))**2
1.7976931348498495e+308
>>> ((2**1023.99999999999)**0.5)**2
1.7976931348498499e+308

>>> ((2**1023.99999999999)**0.5)**2 - 2**1023.99999999999
1.9958403095347198e+292
>>> (sqrt(2**1023.99999999999))**2 - 2**1023.99999999999
-1.9958403095347198e+292

http://mail.python.org/pipermail/python-list/2003-November/238546.html

The math module wraps the platform C library math functions of the same names; math.pow() is most useful if you need (or just want) high compatibility with C extensions calling C's pow().

__builtin__.pow() is the implementation of Python's infix ** operator, and deals with complex numbers, unbounded integer powers, and modular exponentiation too (the C pow() doesn't handle any of those).

** is more complete. math.sqrt is probably just the C implementation of sqrt which is probably related to pow.

Answered by: Blake422 | Posted: 07-01-2022



Answer 2

Both the pow function and the math.sqrt() function can calculate results that are more accurate than what the default float type can store. I think the errors you're seeing is a result of the limitations of floating point math rather than inaccuracies of the functions. Also, since when is a difference of ~10^(-13) a problem when taking the square root of a 7 digit number? Even the most accurate physics calculations seldom requires that many significant digits...

Another reason to use math.sqrt() is that it's easier to read and understand, which generally is a good reason to do things a certain way.

Answered by: Kristian493 | Posted: 07-01-2022



Answer 3

Use decimal to find more precise square roots:

>>> import decimal
>>> decimal.getcontext().prec = 60
>>> decimal.Decimal(8885558).sqrt()
Decimal("2980.86531061032678789963529280900544861029083861907705317042")

Answered by: Darcy647 | Posted: 07-01-2022



Answer 4

Any time you are given a choice between two functions which are built into a language, the more specific function will almost always be equal to or better than the generic one (since if it was worse, the coders would've just implemented it in terms of the generic function). Sqrt is more specific than generic exponentiation so you can expect it's a better choice. And it is, at least in terms of speed. In terms of accuracy, you aren't dealing with enough precision in your numbers to be able to tell.

Note: To clarify, sqrt is faster in Python 3.0. It's slower in older versions of Python. See J.F. Sebastians measurements at Which is faster in Python: x**.5 or math.sqrt(x)? .

Answered by: Max684 | Posted: 07-01-2022



Answer 5

This has to be some kind of platform-specific thing because I get different results:

Python 2.5.1 (r251:54863, Jan 13 2009, 10:26:13) 
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin
>>> 8885558**.5 - math.sqrt(8885558)
0.0

What version of python are you using and what OS?

My guess is that it has something to do with promotion and casting. In other words, since you're doing 8885558**.5, 8885558 has to be promoted to a float. All this is handled differently depending on the operating system, processor, and version of Python. Welcome to the wonderful world of floating point arithmetic. :-)

Answered by: Dexter502 | Posted: 07-01-2022



Answer 6

I got the same issue with you on Win XP Python 2.5.1, while I don't on 32-bit Gentoo Python 2.5.4. It's a matter of C library implementation.

Now, on Win, math.sqrt(8885558)**2 gives 8885558.0000000019, while (8885558**.5)**2 gives 8885557.9999999981, which seem to amount to the same epsilon.

I say that one cannot really say which one is the "better" option.

Answered by: Nicole982 | Posted: 07-01-2022



Answer 7

I don't get the same behavior. Perhaps the error is platform specific? On amd64 I get this:

Python 2.5.2 (r252:60911, Mar 10 2008, 15:14:55) 
[GCC 3.3.5 (propolice)] on openbsd4
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> math.sqrt(8885558) - (8885558**.5)
0.0
>>> (8885558**.5) - math.sqrt(8885558)
0.0

Answered by: Grace237 | Posted: 07-01-2022



Answer 8

In theory math.sqrt should have a higher precision then math.pow. See Newton's method to compute square roots [0]. However the limitation in the number of decimal digits of the python float (or the C double) will probably mask the difference.

[0] http://en.wikipedia.org/wiki/Integer_square_root

Answered by: Adelaide412 | Posted: 07-01-2022



Answer 9

I performed the same test and got the same results, 10103 differences out of 10000000. This was using Python 2.7 in Windows.

The difference is one of rounding. I believe when the two results differ, it is only one ULP which is the smallest possible difference for a float. The true answer lies between the two, but a float doesn't have the ability to represent it exactly and it must be rounded.

As noted in another answer, the decimal module can be used to get better accuracy than a float. I utilized this to get a better idea of the true error, and in all cases the sqrt was closer than the **0.5. Although not by much!

>>> s1 = sqrt(8885558)
>>> s2 = 8885558**0.5
>>> s3 = decimal.Decimal(8885558).sqrt()
>>> s1, s2, s3
(2980.865310610327, 2980.8653106103266, Decimal('2980.865310610326787899635293'))
>>> s3 - decimal.Decimal(s1)
Decimal('-2.268290468226740188598632812E-13')
>>> s3 - decimal.Decimal(s2)
Decimal('2.2791830406379010009765625E-13')

Answered by: Roland288 | Posted: 07-01-2022



Similar questions

c# - python: how accurate math.sqrt(x) function is?

Consider the following code snippet in Python: m = int(math.sqrt(n)) For n = 25, it should give m = 5 (and it does in my shell). But from my C experience I know that using such expression is a bad idea, as sqrt function may return a slightly lower value than the real value, and then after rounding i may get m = 4 instead of m = 5. Is this limitation also involved in python? And if this is ...


performance - Which is faster in Python: x**.5 or math.sqrt(x)?

I've been wondering this for some time. As the title say, which is faster, the actual function or simply raising to the half power? UPDATE This is not a matter of premature optimization. This is simply a question of how the underlying code actually works. What is the theory of how Python code works? I sent Guido van Rossum an email cause I really wanted to know the differences in these method...


c# - python: how accurate math.sqrt(x) function is?

Consider the following code snippet in Python: m = int(math.sqrt(n)) For n = 25, it should give m = 5 (and it does in my shell). But from my C experience I know that using such expression is a bad idea, as sqrt function may return a slightly lower value than the real value, and then after rounding i may get m = 4 instead of m = 5. Is this limitation also involved in python? And if this is ...






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top