Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Python's Decimal function defaulting to 54 places?

Tags:

python

decimal

After inputting

from decimal import *
getcontext().prec = 6
Decimal (1) / Decimal (7)

I get the value

Decimal('0.142857')  

However if I enter Decimal (1.0/7) I get

Decimal('0.142857142857142849212692681248881854116916656494140625')
like image 736
androshalforc Avatar asked Sep 06 '12 01:09

androshalforc


People also ask

How do I get rid of extra decimal places in Python?

They are integers(int()), floating-point numbers(float()) and complex(complex()) data types. Type conversion in python helps to convert a decimal value number(floating number) to an integer. Thus converting float->int removes all decimals from a number.

How do you force two decimal places in Python?

2️⃣ f-string Thus, you can use f'{value: . 2f}' to return a string representation of the number up to two decimal places.

How do I keep 3 decimal places in Python?

Use the round() function to round a float to 3 decimal places, e.g. result = round(6.36789, 3) . The round() function will round the floating-point number to 3 decimal places and will return the result.


1 Answers

The 1.0 / 7 computes a binary floating point number to 17 digits of precision. This happens before the Decimal constructor sees it:

>>> d = 1.0 / 7
>>> type(d)
<type 'float'>
>>> d.as_integer_ratio()
(2573485501354569, 18014398509481984)

The binary fraction, 2573485501354569 / 18014398509481984 is as close as binary floating point can get using 53 bits of precision. It is not exactly 1/7th, but it's pretty close.

The Decimal constructor then converts the binary fraction to as many places as necessary to get an exact decimal equivalent. The result you're are seeing is what you get when you evaluate 2573485501354569 / 18014398509481984 exactly:

>>> from decimal import Decimal, getcontext
>>> getcontext().prec = 100
>>> Decimal(2573485501354569) / Decimal(18014398509481984)
Decimal('0.142857142857142849212692681248881854116916656494140625')

Learning point 1: Binary floating point computes binary fractions to 53 bits of precision. The result is rounded if necessary.

Learning point 2: The Decimal constructor converts binary floating point numbers to decimals losslessly (no rounding). This tends to result in many more digits of precision than you might expect (See the 6th question in the Decimal FAQ).

Learning point 3: The decimal module is designed to treat all numbers as being exact. Only the results of computations get rounded to the context precision. The binary floating point input is converted to decimal exactly and context precision isn't applied until you do a computation with the number (See the final question and answer in the Decimal FAQ for details).

Executive summary: Don't do binary floating point division before handing the numbers to the decimal module. Let it do the work to your desired precision.

Hope this helps :-)

like image 197
Raymond Hettinger Avatar answered Oct 12 '22 12:10

Raymond Hettinger