5

From the documentation page of Decimal, I thought that once we use decimal to compute, it'll be a correct result without any floating error.

But when I try this equation

from decimal import Decimal, getcontext
getcontext().prec = 250

a = Decimal('6')
b = Decimal('500000')

b = a ** b
print('prec: ' + str(getcontext().prec) + ', ', end='')
print(b.ln() / a.ln())

It gives me different result!

enter image description here

I want to calculate the digit of 6**500000 in base-6 representation, so my expect result would be int(b.ln() / a.ln()) + 1, which should be 500001. However, when I set the prec to 250, it gives me the wrong result. How can I solve this?

Also, if I want to output the result without the scientific notation (i.e. 5E+5), what should I do?

niorix
  • 65
  • 6
  • 2
    `decimal` is *adjustable* precision, not *infinite* precision. It says "correctly rounded decimal floating point arithmetic", not "unrounded real number arithmetic". – user2357112 Oct 27 '22 at 06:27
  • please don't upload images of text/code/data/errors when asking questions - instead, paste it in as a formatted code block. thanks! – Michael Delgado Oct 27 '22 at 06:46

3 Answers3

2

If you're after very precise or symbolic math and/or being bitten by IEEE 754 float aliasing, check out SymPy

>>> from sympy import log, N
>>> expr = log(6**50000) / log(6)
>>> N(expr)
50000.0000000000
ti7
  • 16,375
  • 6
  • 40
  • 68
2

The Documentation clearly show the parameters of getcontext()

enter image description here

when you simply execute getcontext() it can show its built-in parameters.

Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])

When you can change getcontext().prec = 250 then it can only overwrite prec value.

enter image description here

the main thing which can effect the result is rounding parameter right after the prec, It is built-in parameter rounding=ROUND_HALF_EVEN. I want to change this to None but it can show an error.

enter image description here

so it can clarify that no matter what we can do it must change even slightly because of rounding parameter.

Note: your result may also effect because of other built-in parameters.

Mehmaam
  • 573
  • 7
  • 22
1

The documentation for Decimal.ln() states:

Return the natural (base e) logarithm of the operand. The result is correctly rounded using the ROUND_HALF_EVEN rounding mode.

When you changed the precision, more digits of the numbers were calculated and they are then rounded down instead of up. The number needs to be rounded because it is not necessarily within the specified precision, or even rational at all.

For outputting results in scientific notation, see this question.

dranjohn
  • 673
  • 7
  • 22