Decimal fixed-point arithmetic¶
The module decimalfp provides a Decimal
number type which can
represent decimal numbers of arbitrary magnitude and arbitrary precision, i.e.
any number of fractional digits.
Usage¶
decimalfp.Decimal
instances are created by giving a value (default:
0) and a precision (i.e the number of fractional digits, default: None).
>>> Decimal()
Decimal(0)
If precision is given, it must be of type int and >= 0.
>>> Decimal(5, 3)
Decimal(5, 3)
>>> Decimal(5555, -3)
ValueError: Precision must be >= 0.
If value is given, it must either be a string (type str or unicode in Python 2.x, bytes or str in Python 3.x), an instance of number.Integral (for example int or long in Python 2.x, int in Python 3.x), number.Rational (for example fractions.Fraction), decimal.Decimal or float or be convertable to a float or an int.
The value is always adjusted to the given precision or the precision is calculated from the given value, if no precision is given.
>>> Decimal(b'12.345')
Decimal('12.345')
>>> Decimal(u'12.345')
Decimal('12.345')
>>> Decimal(u'12.345', 5)
Decimal('12.345', 5)
>>> Decimal(15, 4)
Decimal(15, 4)
>>> Decimal(10 ** 23)
Decimal(100000000000000000000000)
>>> Decimal(10 ** 48)
Decimal(1000000000000000000000000000000000000000000000000)
>>> Decimal(2 ** 48)
Decimal(281474976710656)
>>> Decimal(2 ** 98)
Decimal(316912650057057350374175801344)
>>> Decimal(Fraction(7, 56))
Decimal('0.125')
>>> Decimal(Fraction(8106479329266893, 4503599627370496), 7)
Decimal('1.8', 7)
>>> Decimal(1.8, 7)
Decimal('1.8', 7)
>>> Decimal(decimal.Decimal('-19.26', 5), 3)
Decimal('-19.26', 3)
When the given precision is lower than the precision of the given value, the result is rounded, according to the rounding mode of the current context held by the standard module decimal (which defaults to ROUND_HALF_EVEN, in contrast to the round function in Python 2.x !!!).
>>> Decimal(u'12.345', 2)
Decimal('12.34')
>>> Decimal(u'12.3456', 3)
Decimal('12.346')
>>> Decimal(0.2, 3)
Decimal('0.2', 3)
>>> Decimal(0.2, 17)
Decimal('0.20000000000000001')
>>> Decimal(0.2, 55)
Decimal('0.200000000000000011102230246251565404236316680908203125', 55)
When no precision is given and the given value is a float or a
numbers.Rational (but no Decimal
), the Decimal
constructor
tries to convert value exactly. But, for performance reasons, this is done
only up a fixed limit of fractional digits. This limit defaults to 32 and is
accessible as decimalfp.LIMIT_PREC. If value can not be represented as a
Decimal
within this limit, an exception is raised.
>>> Decimal(0.2)
ValueError: Can't convert 0.2 exactly to Decimal.
>>> Decimal(Fraction(1, 7))
ValueError: Can't convert Fraction(1, 7) exactly to Decimal.
Decimal
does not deal with infinity, division by 0 always raises a
ZeroDivisionError. Likewise, infinite instances of type float or
decimal.Decimal can not be converted to Decimal
instances. The same
is true for the ‘not a number’ instances of these types.
Computations¶
When importing decimalfp, its Decimal
type is registered in Pythons
numerical stack as number.Rational. It supports all operations defined for
that base class and its instances can be mixed in computations with instances
of all numeric types mentioned above.
All numerical operations give an exact result, i.e. they are not automatically
constraint to the precision of the operands or to a number of significant
digits (like the floating-point Decimal type from the standard module
decimal). When the result can not exactly be represented by a
Decimal
instance within the limit given by decimalfp.LIMIT_PREC, an
instance of fractions.Fraction is returned.
Addition and subtraction¶
Adding or subtracting Decimal
instances results in a Decimal
instance with a precision equal to the maximum of the precisions of the
operands.
>>> Decimal('7.3') + Decimal('8.275')
Decimal('15.575')
>>> Decimal('-7.3', 4) + Decimal('8.275')
Decimal('0.975', 4)
In operations with other numerical types the precision of the result is at
least equal to the precision of the involved Decimal
instance, but
may be greater, if neccessary. If the needed precision exceeds
decimalfp.LIMIT_PREC, an instance of fractions.Fraction is returned.
>>> 0.25 + Decimal(3)
Decimal('3.25')
>>> 0.25 - Decimal(-3, 5)
Decimal('3.25', 5)
>>> 0.725 + Decimal('3')
Fraction(33551817223910195, 9007199254740992)
>>> Decimal('3') + Fraction(1, 7)
Fraction(22, 7)
Multiplication and division¶
Multiplying Decimal
instances results in a Decimal
instance
with precision equal to the sum of the precisions of the operands.
>>> Decimal('5.000') * Decimal('2.5')
Decimal('12.5', 4)
Dividing Decimal
instances results in a Decimal
instance
with precision at least equal to max(0, numerator.precision -
denominator.precision), but may be greater, if needed.
>>> Decimal('5.2000') / Decimal('2.5')
Decimal('2.08', 3)
>>> Decimal('5.2003') / Decimal('2.5')
Decimal('2.08012')
In operations with other numerical types the precision of the result is at
least equal to the precision of the involved Decimal
instance, but
may be greater, if neccessary. If the needed precision exceeds
decimalfp.LIMIT_PREC, an instance of fractions.Fraction is returned.
>>> 3 * Decimal('7.5')
Decimal('22.5')
>>> Decimal(5) * 0.25
Decimal('1.25')
>>> Decimal('3') * Fraction(1, 7)
Fraction(3, 7)
Rounding¶
Decimal
supports rounding via the built-in function round.
Note
In Python 2.x the function round uses the rounding mode ROUND_HALF_UP and always returns a float, while in Python 3.x it rounds according to ROUND_HALF_EVEN and returns an int when called with one argument, otherwise the same type as the number to be rounded.
Python 2.x:
>>> round(Decimal('12.345'))
12.0
>>> round(Decimal('12.345'), 2)
12.35
>>> round(Decimal('1234.5'), -2)
1200.0
Python 3.x:
>>> round(Decimal('12.345'))
12
>>> round(Decimal('12.345'), 2)
Decimal('12.34')
>>> round(Decimal('1234.5'), -2)
Decimal(1200)
In addition, via the method adjusted()
a Decimal
with a
different precision can be derived, supporting all rounding modes defined by
the standard library module decimal.
>>> d = Decimal('12.345')
>>> d.adjusted(2) # default rounding mode is ROUND_HALF_EVEN !
Decimal('12.34')
>>> d.adjusted(2, ROUND_HALF_UP)
Decimal('12.35')
>>> d.adjusted(1, ROUND_UP)
Decimal('12.4')
For the details of the different rounding modes see the documentation of the standard library module decimal.
round and adjusted only allow to round to a quantum that’s a power to 10.
The method quantize()
can be used to round to any quantum and it does
also support all rounding modes mentioned above.
>>> d = Decimal('12.345')
>>># equivalent to round(d, 2) or d.adjusted(2)
>>># (default rounding mode ROUND_HALF_EVEN):
>>> d.quantize(Decimal('0.01'))
Decimal('12.34')
>>> d.quantize(Decimal('0.05'))
Decimal('12.35')
>>> d.quantize('0.6')
Decimal('12.6')
>>> d.quantize(4)
Decimal('12')
Class Decimal¶
-
class
decimalfp.
Decimal
¶ Decimal number with a given number of fractional digits.
Parameters: - value (see below) – numerical value (default: 0)
- precision (int) – number of fractional digits (default: None)
If value is given, it must either be a string (type str or unicode in Python 2.x, bytes or str in Python 3.x), an instance of number.Integral (for example int or long in Python 2.x, int in Python 3.x), number.Rational (for example fractions.Fraction), decimal.Decimal or float or be convertable to a float or an int.
If a string is given as value, it must be a string in one of two formats:
- [+|-]<int>[.<frac>][<e|E>[+|-]<exp>] or
- [+|-].<frac>[<e|E>[+|-]<exp>].
Returns: Decimal
instance derived from value according to precisionThe value is always adjusted to the given precision or the precision is calculated from the given value, if no precision is given. For performance reasons, in the latter case the conversion of a numbers.Rational (like fractions.Fraction) or a float tries to give an exact result as a
Decimal
only up to a fixed limit of fractional digits. This limit defaults to 32 and is accessible as decimalfp.LIMIT_PREC.Raises: TypeError
– precision is given, but not of type int.TypeError
– value is not an instance of the types listed above and not convertable to float or int.ValueError
– precision is given, but not >= 0.ValueError
– value can not be converted to a Decimal (with a number of fractional digits <= LIMIT_PREC if no precision is given).
Decimal
instances are immutable.-
__abs__
¶ abs(self)
-
__add__
¶ x + y
-
__ceil__
()¶ math.ceil(self)
-
__div__
¶ x / y
-
__eq__
¶ x.__eq__(y) <==> x==y
-
__floor__
()¶ math.floor(self)
-
__format__
()¶ Return self converted to a string according to given format specifier.
Parameters: fmtSpec (str) – a standard format specifier for a number Returns: self converted to a string according to fmtSpec Return type: str
-
__ge__
¶ x.__ge__(y) <==> x>=y
-
__gt__
¶ x.__gt__(y) <==> x>y
-
__hash__
¶ hash(self)
-
__le__
¶ x.__le__(y) <==> x<=y
-
__lt__
¶ x.__lt__(y) <==> x<y
-
__mul__
¶ x * y
-
__neg__
¶ -self
-
__pos__
¶ +self
-
__pow__
¶ x ** y
If y is an integer (or a Rational with denominator = 1), the result will be a Decimal. Otherwise, the result will be a float or complex since roots are generally irrational.
mod must always be None (otherwise a TypeError is raised).
-
__radd__
¶ x.__radd__(y) <==> y+x
-
__rdiv__
¶ x.__rdiv__(y) <==> y/x
-
__repr__
¶ repr(self)
-
__rmul__
¶ x.__rmul__(y) <==> y*x
-
__round__
()¶ round(self [, ndigits])
Round self to a given precision in decimal digits (default 0). ndigits may be negative.
Note: This method is called by the built-in round function only in Python 3.x! It returns an int when called with one argument, otherwise a
Decimal
.
-
__rsub__
¶ x.__rsub__(y) <==> y-x
-
__rtruediv__
¶ x.__rtruediv__(y) <==> y/x
-
__str__
¶ str(self)
-
__sub__
¶ x - y
-
__truediv__
¶ x / y
-
adjusted
()¶ Return copy of self, adjusted to the given precision, using the given rounding mode.
Parameters: - precision (int) – number of fractional digits (default: None)
- rounding (str) – rounding mode (default: None)
Returns: Decimal
instance derived from self, adjusted to the given precision, using the given rounding modeIf no precision is given, the result is adjusted to the minimum precision preserving x == x.adjusted().
If no rounding mode is given, the default mode from the current context (from module decimal) is used.
If the given precision is less than the precision of self, the result is rounded and thus information may be lost.
-
as_integer_ratio
()¶ Return the pair of numerator and denominator with the smallest positive denominator, whose ratio is equal to self.
-
as_tuple
()¶ Return a tuple (sign, coeff, exp) so that self == (-1) ** sign * coeff * 10 ** exp.
-
denominator
¶ Return the smallest positive denominator from the pairs of integers, whose ratio is equal to self.
-
from_decimal
()¶ Convert a finite decimal number to a
Decimal
.Parameters: d (see below) – decimal number to be converted to a Decimal
d can be of type
Decimal
, numbers.Integral or decimal.Decimal.Returns: Decimal
instance derived from dRaises: TypeError
– d is not an instance of the types listed above.ValueError
– d can not be converted to aDecimal
.
-
from_float
()¶ Convert a finite float (or int) to a
Decimal
.Parameters: f (float or int) – number to be converted to a Decimal
Returns: Decimal
instance derived from fRaises: TypeError
– f is neither a float nor an int.ValueError
– f can not be converted to aDecimal
with a precision <= LIMIT_PREC.
Beware that Decimal.from_float(0.3) != Decimal(‘0.3’).
-
from_real
()¶ Convert a Real number to a
Decimal
.Parameters: Returns: Decimal
instance derived from rRaises: TypeError
– r is not an instance of numbers.Real.ValueError
– exact is True and r can not exactly be converted to aDecimal
with a precision <= LIMIT_PREC.
If exact is False and r can not exactly be represented by a Decimal with a precision <= LIMIT_PREC, the result is rounded to a precision = LIMIT_PREC.
-
imag
¶ The imaginary part of self.
Returns 0 (Real numbers have no imaginary component).
-
magnitude
¶ Return magnitude of self in terms of power to 10, i.e. the smallest integer exp so that 10 ** exp >= self.
-
numerator
¶ Return the numerator from the pair of integers with the smallest positive denominator, whose ratio is equal to self.
-
precision
¶ Return precision of self.
-
real
¶ The real part of self.
Returns self (Real numbers are their real component).
Rounding modes¶
Decimal supports all rounding modes defined by the standard library module decimal: ROUND_DOWN, ROUND_UP, ROUND_HALF_DOWN, ROUND_HALF_UP, ROUND_HALF_EVEN, ROUND_CEILING, ROUND_FLOOR and ROUND_05UP. It uses the rounding mode set as default in that module.
As shortcut to get or set the rounding mode, the module decimalfp provides the following two functions: