Arbitrary precision of square roots

I was quite disappointed when decimal.Decimal(math.sqrt(2)) yielded

Decimal('1.4142135623730951454746218587388284504413604736328125')

and the digits after the 15th decimal place turned out wrong. (Despite happily giving you much more than 15 digits!)

How can I get the first m correct digits in the decimal expansion of sqrt(n) in Python?


Solution 1:

Use the sqrt method on Decimal

>>> from decimal import *
>>> getcontext().prec = 100  # Change the precision
>>> Decimal(2).sqrt()
Decimal('1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573')

Solution 2:

You can try bigfloat. Example from the project page:

from bigfloat import *
sqrt(2, precision(100))  # compute sqrt(2) with 100 bits of precision

Solution 3:

IEEE standard double precision floating point numbers only have 16 digits of precision. Any software/hardware that uses IEEE cannot do better:

http://en.wikipedia.org/wiki/IEEE_754-2008

You'd need a special BigDecimal class implementation, with all math functions implemented to use it. Python has such a thing:

https://literateprograms.org/arbitrary-precision_elementary_mathematical_functions__python_.html

Solution 4:

How can I get the first m correct digits in the decimal expansion of sqrt(n) in Python?

One way is to calculate integer square root of the number multiplied by required power of 10. For example, to see the first 20 decimal places of sqrt(2), you can do:

>>> from gmpy2 import isqrt
>>> num = 2
>>> prec = 20
>>> isqrt(num * 10**(2*prec)))
mpz(141421356237309504880)

The isqrt function is actually quite easy to implement yourself using the algorithm provided on the Wikipedia page.