简体   繁体   中英

Can I keep decimal precision while using integer division in Python?

When I divide 2/3 I get 0.66666666, when I do 2//3 I get 0.

Is there any way to compute integer division while still keeping the decimal points?

Edit: looks like I may have confused a lot of you, my bad. So what my professor told me that since standard division(2/3) will only return 0.666666666666 up to 203 digits, it is not useful when I want to do computations that requires more than 203 digits after the decimal point. I am wondering if there is a way to do 2//3 (which will return 0) but somehow still get the .6666 in the end

For certain limited decimals, you can use Python's float .as_integer_ratio() method:

>>> 0.5.as_integer_ratio()
(1, 2)

For 2/3, which is not exactly representable in decimal, this starts to give less desirable results:

>>> (2/3).as_integer_ratio()
(6004799503160661, 9007199254740992)      # approximation of 2/3

For arbitrary precision of rational numbers, use fractions in the Python library:

>>> import fractions
>>> fractions.Fraction('2/3')
Fraction(2, 3)
>>> Frac=fractions.Fraction
>>> Frac('2/3') + Frac('1/3') + Frac('1/10')
Fraction(11, 10)
>>> Frac('2/3') + Frac('1/6') + Frac('1/10')
Fraction(14, 15)

Then if you want a more accurate representation of that in decimal, use the Decimal library to convert the integer numerator and denominator to an arbitrary precision decimal:

>>> f=Frac('2/3') + Frac('1/6') + Frac('1/10')
>>> f
Fraction(14, 15)
>>> f.numerator
14
>>> f.denominator
15
>>> import decimal
>>> decimal.Decimal(f.numerator) / decimal.Decimal(f.denominator)
Decimal('0.9333333333333333333333333333')

You can also cast one integer to a float before division.

In [1]: float(2)/3
Out[1]: 0.6666666666666666

This will prevent integer truncation and give you a result as a float .

Perhaps take a look at decimal.Decimal() :

>>> import decimal
>>> x = decimal.Decimal(2/3)
>>> x
Decimal('0.66666666666666662965923251249478198587894439697265625')

// is a floor division, it will give you the integer floor of the result. No matter you use 2//3 or float(2)//3 . You can not keep precision when using // .

In my environment (python2.7.6) 2//3 return 0 and float(2)//3 return 0.0 , neither can keep the precision.

A similar question maybe helpful for you.

This is not a direct answer to your question but it will help you to udnerstand.

I am posting two link which explains very much details about the implementation:

Here is something which we need to aware of:

>>> 2/3
0
>>> 2/3.0
0.6666666666666666
>>> 2//3
0
>>> -2//3
-1
>>>

from the PEP-0238

The current division (/) operator has an ambiguous meaning for numerical arguments: it returns the floor of the mathematical result of division if the arguments are ints or longs, but it returns a reasonable approximation of the division result if the arguments are floats or complex. This makes expressions expecting float or complex results error-prone when integers are not expected but possible as inputs.

We propose to fix this by introducing different operators for different operations: x/y to return a reasonable approximation of the mathematical result of the division ("true division"), x//y to return the floor ("floor division"). We call the current, mixed meaning of x/y "classic division". - Classic division will remain the default in the Python 2.x series; true division will be standard in Python 3.0.

- The // operator will be available to request floor division
  unambiguously.

- The future division statement, spelled "from __future__ import
  division", will change the / operator to mean true division
  throughout the module.

- A command line option will enable run-time warnings for classic
  division applied to int or long arguments; another command line
  option will make true division the default.

- The standard library will use the future division statement and
  the // operator when appropriate, so as to completely avoid
  classic division.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM