29

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?

Randomblue
  • 112,777
  • 145
  • 353
  • 547
  • 6
    To be clear, the loss of precision happens in `math.sqrt(2)`, which uses floating-point. Making it a `Decimal` afterwards doesn't fix that. – wjandrea Jan 21 '22 at 22:50

4 Answers4

68

Use the sqrt method on Decimal

>>> from decimal import *
>>> getcontext().prec = 100  # Change the precision
>>> Decimal(2).sqrt()
Decimal('1.414213562373095048801688724209698078569671875376948073176679737990732478462107038850387534327641573')
wjandrea
  • 28,235
  • 9
  • 60
  • 81
Nick Craig-Wood
  • 52,955
  • 12
  • 126
  • 132
7

You can try bigfloat. Example from the project page:

from bigfloat import *
sqrt(2, precision(100))  # compute sqrt(2) with 100 bits of precision
wong2
  • 34,358
  • 48
  • 134
  • 179
4

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

wjandrea
  • 28,235
  • 9
  • 60
  • 81
duffymo
  • 305,152
  • 44
  • 369
  • 561
1

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.

Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • 5
    This is pretty much exactly what the `decimal` module is doing to compute `Decimal(2).sqrt()`. :-) – Mark Dickinson Sep 18 '15 at 12:06
  • 1
    @Mark: Good to know. Although, last time I tried it, it was much slower than doing this "manually". – Eugene Yarmash Sep 18 '15 at 12:12
  • 1
    Yeah, the Python 2 decimal module was pure Python, and has never been known for its speed. It should be a bit better in Python 3 (or using the `cdecimal` PyPI backport for Python 2). – Mark Dickinson Sep 18 '15 at 12:17