mirror of
https://github.com/python/cpython.git
synced 2025-07-29 06:05:00 +00:00
Comments and docs cleanups, and some little fixes, provided by Santiágo Peresón
This commit is contained in:
parent
caebe22038
commit
ac4ae4baf7
1 changed files with 205 additions and 184 deletions
197
Lib/decimal.py
197
Lib/decimal.py
|
@ -29,8 +29,8 @@ and IEEE standard 854-1987:
|
|||
|
||||
Decimal floating point has finite precision with arbitrarily large bounds.
|
||||
|
||||
The purpose of the module is to support arithmetic using familiar
|
||||
"schoolhouse" rules and to avoid the some of tricky representation
|
||||
The purpose of this module is to support arithmetic using familiar
|
||||
"schoolhouse" rules and to avoid some of the tricky representation
|
||||
issues associated with binary floating point. The package is especially
|
||||
useful for financial applications or for contexts where users have
|
||||
expectations that are at odds with binary floating point (for instance,
|
||||
|
@ -160,17 +160,17 @@ class DecimalException(ArithmeticError):
|
|||
called if the others are present. This isn't actually used for
|
||||
anything, though.
|
||||
|
||||
handle -- Called when context._raise_error is called and the
|
||||
trap_enabler is set. First argument is self, second is the
|
||||
context. More arguments can be given, those being after
|
||||
the explanation in _raise_error (For example,
|
||||
context._raise_error(NewError, '(-x)!', self._sign) would
|
||||
call NewError().handle(context, self._sign).)
|
||||
|
||||
To define a new exception, it should be sufficient to have it derive
|
||||
from DecimalException.
|
||||
"""
|
||||
def handle(self, context, *args):
|
||||
"""Called when context._raise_error is called and trap_enabler is set.
|
||||
|
||||
First argument is self, second is the context. More arguments can
|
||||
be given, those being after the explanation in _raise_error (For
|
||||
example, context._raise_error(NewError, '(-x)!', self._sign) would
|
||||
call NewError().handle(context, self._sign).)
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
|
@ -185,6 +185,7 @@ class Clamped(DecimalException):
|
|||
this latter case, the exponent is reduced to fit and the corresponding
|
||||
number of zero digits are appended to the coefficient ("fold-down").
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
class InvalidOperation(DecimalException):
|
||||
|
@ -211,6 +212,7 @@ class InvalidOperation(DecimalException):
|
|||
return Decimal( (args[1]._sign, args[1]._int, 'n') )
|
||||
return NaN
|
||||
|
||||
|
||||
class ConversionSyntax(InvalidOperation):
|
||||
"""Trying to convert badly formed string.
|
||||
|
||||
|
@ -218,10 +220,10 @@ class ConversionSyntax(InvalidOperation):
|
|||
converted to a number and it does not conform to the numeric string
|
||||
syntax. The result is [0,qNaN].
|
||||
"""
|
||||
|
||||
def handle(self, context, *args):
|
||||
return (0, (0,), 'n') # Passed to something which uses a tuple.
|
||||
|
||||
|
||||
class DivisionByZero(DecimalException, ZeroDivisionError):
|
||||
"""Division by 0.
|
||||
|
||||
|
@ -234,12 +236,12 @@ class DivisionByZero(DecimalException, ZeroDivisionError):
|
|||
or of the signs of the operands for divide, or is 1 for an odd power of
|
||||
-0, for power.
|
||||
"""
|
||||
|
||||
def handle(self, context, sign, double = None, *args):
|
||||
if double is not None:
|
||||
return (Infsign[sign],)*2
|
||||
return Infsign[sign]
|
||||
|
||||
|
||||
class DivisionImpossible(InvalidOperation):
|
||||
"""Cannot perform the division adequately.
|
||||
|
||||
|
@ -247,10 +249,10 @@ class DivisionImpossible(InvalidOperation):
|
|||
divide-integer or remainder operation had too many digits (would be
|
||||
longer than precision). The result is [0,qNaN].
|
||||
"""
|
||||
|
||||
def handle(self, context, *args):
|
||||
return (NaN, NaN)
|
||||
|
||||
|
||||
class DivisionUndefined(InvalidOperation, ZeroDivisionError):
|
||||
"""Undefined result of division.
|
||||
|
||||
|
@ -258,12 +260,12 @@ class DivisionUndefined(InvalidOperation, ZeroDivisionError):
|
|||
attempted (during a divide-integer, divide, or remainder operation), and
|
||||
the dividend is also zero. The result is [0,qNaN].
|
||||
"""
|
||||
|
||||
def handle(self, context, tup=None, *args):
|
||||
if tup is not None:
|
||||
return (NaN, NaN) #for 0 %0, 0 // 0
|
||||
return (NaN, NaN) # For 0 %0, 0 // 0
|
||||
return NaN
|
||||
|
||||
|
||||
class Inexact(DecimalException):
|
||||
"""Had to round, losing information.
|
||||
|
||||
|
@ -277,6 +279,7 @@ class Inexact(DecimalException):
|
|||
"""
|
||||
pass
|
||||
|
||||
|
||||
class InvalidContext(InvalidOperation):
|
||||
"""Invalid context. Unknown rounding, for example.
|
||||
|
||||
|
@ -287,10 +290,10 @@ class InvalidContext(InvalidOperation):
|
|||
was specified. These aspects of the context need only be checked when
|
||||
the values are required to be used. The result is [0,qNaN].
|
||||
"""
|
||||
|
||||
def handle(self, context, *args):
|
||||
return NaN
|
||||
|
||||
|
||||
class Rounded(DecimalException):
|
||||
"""Number got rounded (not necessarily changed during rounding).
|
||||
|
||||
|
@ -304,6 +307,7 @@ class Rounded(DecimalException):
|
|||
"""
|
||||
pass
|
||||
|
||||
|
||||
class Subnormal(DecimalException):
|
||||
"""Exponent < Emin before rounding.
|
||||
|
||||
|
@ -316,6 +320,7 @@ class Subnormal(DecimalException):
|
|||
"""
|
||||
pass
|
||||
|
||||
|
||||
class Overflow(Inexact, Rounded):
|
||||
"""Numerical overflow.
|
||||
|
||||
|
@ -337,7 +342,6 @@ class Overflow(Inexact, Rounded):
|
|||
result is 0, or is [1,inf] otherwise. In all cases, Inexact and Rounded
|
||||
will also be raised.
|
||||
"""
|
||||
|
||||
def handle(self, context, sign, *args):
|
||||
if context.rounding in (ROUND_HALF_UP, ROUND_HALF_EVEN,
|
||||
ROUND_HALF_DOWN, ROUND_UP):
|
||||
|
@ -368,6 +372,8 @@ class Underflow(Inexact, Rounded, Subnormal):
|
|||
|
||||
In all cases, Inexact, Rounded, and Subnormal will also be raised.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
# List of public traps and flags
|
||||
_signals = [Clamped, DivisionByZero, Inexact, Overflow, Rounded,
|
||||
|
@ -379,25 +385,27 @@ _condition_map = {ConversionSyntax:InvalidOperation,
|
|||
DivisionUndefined:InvalidOperation,
|
||||
InvalidContext:InvalidOperation}
|
||||
|
||||
##### Context Functions #######################################
|
||||
##### Context Functions #####################################################
|
||||
|
||||
# The getcontext() and setcontext() function manage access to a thread-local
|
||||
# current context. Py2.4 offers direct support for thread locals. If that
|
||||
# is not available, use threading.currentThread() which is slower but will
|
||||
# work for older Pythons. If threads are not part of the build, create a
|
||||
# mock threading object with threading.local() returning the module namespace.
|
||||
# mock threading object with threading.local() returning the module
|
||||
# namespace.
|
||||
|
||||
try:
|
||||
import threading
|
||||
except ImportError:
|
||||
# Python was compiled without threads; create a mock object instead
|
||||
import sys
|
||||
class MockThreading:
|
||||
class MockThreading(object):
|
||||
def local(self, sys=sys):
|
||||
return sys.modules[__name__]
|
||||
threading = MockThreading()
|
||||
del sys, MockThreading
|
||||
|
||||
|
||||
try:
|
||||
threading.local
|
||||
|
||||
|
@ -459,7 +467,7 @@ else:
|
|||
del threading, local # Don't contaminate the namespace
|
||||
|
||||
|
||||
##### Decimal class ###########################################
|
||||
##### Decimal class ##########################################################
|
||||
|
||||
class Decimal(object):
|
||||
"""Floating point class for decimal arithmetic."""
|
||||
|
@ -475,7 +483,7 @@ class Decimal(object):
|
|||
|
||||
>>> Decimal('3.14') # string input
|
||||
Decimal("3.14")
|
||||
>>> Decimal((0, (3, 1, 4), -2)) # tuple input (sign, digit_tuple, exponent)
|
||||
>>> Decimal((0, (3, 1, 4), -2)) # tuple (sign, digit_tuple, exponent)
|
||||
Decimal("3.14")
|
||||
>>> Decimal(314) # int or long
|
||||
Decimal("314")
|
||||
|
@ -514,12 +522,13 @@ class Decimal(object):
|
|||
# tuple/list conversion (possibly from as_tuple())
|
||||
if isinstance(value, (list,tuple)):
|
||||
if len(value) != 3:
|
||||
raise ValueError, 'Invalid arguments'
|
||||
raise ValueError('Invalid arguments')
|
||||
if value[0] not in (0,1):
|
||||
raise ValueError, 'Invalid sign'
|
||||
raise ValueError('Invalid sign')
|
||||
for digit in value[1]:
|
||||
if not isinstance(digit, (int,long)) or digit < 0:
|
||||
raise ValueError, "The second value in the tuple must be composed of non negative integer elements."
|
||||
raise ValueError("The second value in the tuple must be "+
|
||||
"composed of non negative integer elements.")
|
||||
|
||||
self._sign = value[0]
|
||||
self._int = tuple(value[1])
|
||||
|
@ -568,7 +577,8 @@ class Decimal(object):
|
|||
self._sign, self._int, self._exp = _string2exact(value)
|
||||
except ValueError:
|
||||
self._is_special = True
|
||||
self._sign, self._int, self._exp = context._raise_error(ConversionSyntax)
|
||||
self._sign, self._int, self._exp = \
|
||||
context._raise_error(ConversionSyntax)
|
||||
return self
|
||||
|
||||
raise TypeError("Cannot convert %r to Decimal" % value)
|
||||
|
@ -670,7 +680,7 @@ class Decimal(object):
|
|||
if self_adjusted == other_adjusted and \
|
||||
self._int + (0,)*(self._exp - other._exp) == \
|
||||
other._int + (0,)*(other._exp - self._exp):
|
||||
return 0 #equal, except in precision. ([0]*(-x) = [])
|
||||
return 0 # Equal, except in precision. ([0]*(-x) = [])
|
||||
elif self_adjusted > other_adjusted and self._int[0] != 0:
|
||||
return (-1)**self._sign
|
||||
elif self_adjusted < other_adjusted and other._int[0] != 0:
|
||||
|
@ -681,7 +691,7 @@ class Decimal(object):
|
|||
context = getcontext()
|
||||
|
||||
context = context._shallow_copy()
|
||||
rounding = context._set_rounding(ROUND_UP) #round away from 0
|
||||
rounding = context._set_rounding(ROUND_UP) # Round away from 0
|
||||
|
||||
flags = context._ignore_all_flags()
|
||||
res = self.__sub__(other, context=context)
|
||||
|
@ -719,7 +729,7 @@ class Decimal(object):
|
|||
if other is NotImplemented:
|
||||
return other
|
||||
|
||||
#compare(NaN, NaN) = NaN
|
||||
# Compare(NaN, NaN) = NaN
|
||||
if (self._is_special or other and other._is_special):
|
||||
ans = self._check_nans(other, context)
|
||||
if ans:
|
||||
|
@ -1052,8 +1062,8 @@ class Decimal(object):
|
|||
ans = self._check_nans(context=context)
|
||||
if ans:
|
||||
return ans
|
||||
|
||||
return Decimal(self) # Must be infinite, and incrementing makes no difference
|
||||
# Must be infinite, and incrementing makes no difference
|
||||
return Decimal(self)
|
||||
|
||||
L = list(self._int)
|
||||
L[-1] += 1
|
||||
|
@ -1222,7 +1232,6 @@ class Decimal(object):
|
|||
return context._raise_error(DivisionByZero, 'x / 0', sign)
|
||||
|
||||
# OK, so neither = 0, INF or NaN
|
||||
|
||||
shouldround = context._rounding_decision == ALWAYS_ROUND
|
||||
|
||||
# If we're dividing into ints, and self < other, stop.
|
||||
|
@ -1373,7 +1382,7 @@ class Decimal(object):
|
|||
# ignored in the calling function.
|
||||
context = context._shallow_copy()
|
||||
flags = context._ignore_flags(Rounded, Inexact)
|
||||
#keep DivisionImpossible flags
|
||||
# Keep DivisionImpossible flags
|
||||
(side, r) = self.__divmod__(other, context=context)
|
||||
|
||||
if r._isnan():
|
||||
|
@ -1418,7 +1427,8 @@ class Decimal(object):
|
|||
if r > comparison or decrease and r == comparison:
|
||||
r._sign, comparison._sign = s1, s2
|
||||
context.prec += 1
|
||||
if len(side.__add__(Decimal(1), context=context)._int) >= context.prec:
|
||||
numbsquant = len(side.__add__(Decimal(1), context=context)._int)
|
||||
if numbsquant >= context.prec:
|
||||
context.prec -= 1
|
||||
return context._raise_error(DivisionImpossible)[1]
|
||||
context.prec -= 1
|
||||
|
@ -1453,7 +1463,7 @@ class Decimal(object):
|
|||
context = getcontext()
|
||||
return context._raise_error(InvalidContext)
|
||||
elif self._isinfinity():
|
||||
raise OverflowError, "Cannot convert infinity to long"
|
||||
raise OverflowError("Cannot convert infinity to long")
|
||||
if self._exp >= 0:
|
||||
s = ''.join(map(str, self._int)) + '0'*self._exp
|
||||
else:
|
||||
|
@ -1530,7 +1540,8 @@ class Decimal(object):
|
|||
return ans
|
||||
context._raise_error(Inexact)
|
||||
context._raise_error(Rounded)
|
||||
return context._raise_error(Overflow, 'above Emax', ans._sign)
|
||||
c = context._raise_error(Overflow, 'above Emax', ans._sign)
|
||||
return c
|
||||
return ans
|
||||
|
||||
def _round(self, prec=None, rounding=None, context=None):
|
||||
|
@ -1727,10 +1738,9 @@ class Decimal(object):
|
|||
return Infsign[sign]
|
||||
return Decimal( (sign, (0,), 0) )
|
||||
|
||||
#with ludicrously large exponent, just raise an overflow and return inf.
|
||||
if not modulo and n > 0 and (self._exp + len(self._int) - 1) * n > context.Emax \
|
||||
and self:
|
||||
|
||||
# With ludicrously large exponent, just raise an overflow and return inf.
|
||||
if not modulo and n > 0 \
|
||||
and (self._exp + len(self._int) - 1) * n > context.Emax and self:
|
||||
tmp = Decimal('inf')
|
||||
tmp._sign = sign
|
||||
context._raise_error(Rounded)
|
||||
|
@ -1816,7 +1826,7 @@ class Decimal(object):
|
|||
|
||||
if exp._isinfinity() or self._isinfinity():
|
||||
if exp._isinfinity() and self._isinfinity():
|
||||
return self #if both are inf, it is OK
|
||||
return self # If both are inf, it is OK
|
||||
if context is None:
|
||||
context = getcontext()
|
||||
return context._raise_error(InvalidOperation,
|
||||
|
@ -1848,7 +1858,8 @@ class Decimal(object):
|
|||
|
||||
if self._is_special:
|
||||
if self._isinfinity():
|
||||
return context._raise_error(InvalidOperation, 'rescale with an INF')
|
||||
return context._raise_error(InvalidOperation,
|
||||
'rescale with an INF')
|
||||
|
||||
ans = self._check_nans(context=context)
|
||||
if ans:
|
||||
|
@ -1960,7 +1971,6 @@ class Decimal(object):
|
|||
ans = ans.__add__(tmp.__mul__(Decimal((0, (8,1,9), -3)),
|
||||
context=context), context=context)
|
||||
ans._exp -= 1 + tmp.adjusted() // 2
|
||||
|
||||
# ans is now a linear approximation.
|
||||
|
||||
Emax, Emin = context.Emax, context.Emin
|
||||
|
@ -1977,7 +1987,7 @@ class Decimal(object):
|
|||
if context.prec == maxp:
|
||||
break
|
||||
|
||||
#round to the answer's precision-- the only error can be 1 ulp.
|
||||
# Round to the answer's precision-- the only error can be 1 ulp.
|
||||
context.prec = firstprec
|
||||
prevexp = ans.adjusted()
|
||||
ans = ans._round(context=context)
|
||||
|
@ -2052,13 +2062,13 @@ class Decimal(object):
|
|||
ans = self
|
||||
c = self.__cmp__(other)
|
||||
if c == 0:
|
||||
# if both operands are finite and equal in numerical value
|
||||
# If both operands are finite and equal in numerical value
|
||||
# then an ordering is applied:
|
||||
#
|
||||
# if the signs differ then max returns the operand with the
|
||||
# If the signs differ then max returns the operand with the
|
||||
# positive sign and min returns the operand with the negative sign
|
||||
#
|
||||
# if the signs are the same then the exponent is used to select
|
||||
# If the signs are the same then the exponent is used to select
|
||||
# the result.
|
||||
if self._sign != other._sign:
|
||||
if self._sign:
|
||||
|
@ -2079,7 +2089,7 @@ class Decimal(object):
|
|||
def min(self, other, context=None):
|
||||
"""Returns the smaller value.
|
||||
|
||||
like min(self, other) except if one is not a number, returns
|
||||
Like min(self, other) except if one is not a number, returns
|
||||
NaN (and signals if one is sNaN). Also rounds.
|
||||
"""
|
||||
other = _convert_other(other)
|
||||
|
@ -2087,7 +2097,7 @@ class Decimal(object):
|
|||
return other
|
||||
|
||||
if self._is_special or other._is_special:
|
||||
# if one operand is a quiet NaN and the other is number, then the
|
||||
# If one operand is a quiet NaN and the other is number, then the
|
||||
# number is always returned
|
||||
sn = self._isnan()
|
||||
on = other._isnan()
|
||||
|
@ -2101,13 +2111,13 @@ class Decimal(object):
|
|||
ans = self
|
||||
c = self.__cmp__(other)
|
||||
if c == 0:
|
||||
# if both operands are finite and equal in numerical value
|
||||
# If both operands are finite and equal in numerical value
|
||||
# then an ordering is applied:
|
||||
#
|
||||
# if the signs differ then max returns the operand with the
|
||||
# If the signs differ then max returns the operand with the
|
||||
# positive sign and min returns the operand with the negative sign
|
||||
#
|
||||
# if the signs are the same then the exponent is used to select
|
||||
# If the signs are the same then the exponent is used to select
|
||||
# the result.
|
||||
if self._sign != other._sign:
|
||||
if other._sign:
|
||||
|
@ -2146,7 +2156,7 @@ class Decimal(object):
|
|||
except TypeError:
|
||||
return 0
|
||||
|
||||
# support for pickling, copy, and deepcopy
|
||||
# Support for pickling, copy, and deepcopy
|
||||
def __reduce__(self):
|
||||
return (self.__class__, (str(self),))
|
||||
|
||||
|
@ -2160,19 +2170,20 @@ class Decimal(object):
|
|||
return self # My components are also immutable
|
||||
return self.__class__(str(self))
|
||||
|
||||
##### Context class ###########################################
|
||||
##### Context class ##########################################################
|
||||
|
||||
|
||||
# get rounding method function:
|
||||
rounding_functions = [name for name in Decimal.__dict__.keys() if name.startswith('_round_')]
|
||||
# Get rounding method function:
|
||||
rounding_functions = [name for name in Decimal.__dict__.keys()
|
||||
if name.startswith('_round_')]
|
||||
for name in rounding_functions:
|
||||
#name is like _round_half_even, goes to the global ROUND_HALF_EVEN value.
|
||||
# Name is like _round_half_even, goes to the global ROUND_HALF_EVEN value.
|
||||
globalname = name[1:].upper()
|
||||
val = globals()[globalname]
|
||||
Decimal._pick_rounding_function[val] = name
|
||||
|
||||
del name, val, globalname, rounding_functions
|
||||
|
||||
|
||||
class ContextManager(object):
|
||||
"""Helper class to simplify Context management.
|
||||
|
||||
|
@ -2197,12 +2208,13 @@ class ContextManager(object):
|
|||
def __exit__(self, t, v, tb):
|
||||
setcontext(self.saved_context)
|
||||
|
||||
|
||||
class Context(object):
|
||||
"""Contains the context for a Decimal instance.
|
||||
|
||||
Contains:
|
||||
prec - precision (for use in rounding, division, square roots..)
|
||||
rounding - rounding type. (how you round)
|
||||
rounding - rounding type (how you round).
|
||||
_rounding_decision - ALWAYS_ROUND, NEVER_ROUND -- do you round?
|
||||
traps - If traps[exception] = 1, then the exception is
|
||||
raised when it is caused. Otherwise, a value is
|
||||
|
@ -2243,9 +2255,13 @@ class Context(object):
|
|||
def __repr__(self):
|
||||
"""Show the current context."""
|
||||
s = []
|
||||
s.append('Context(prec=%(prec)d, rounding=%(rounding)s, Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d' % vars(self))
|
||||
s.append('flags=[' + ', '.join([f.__name__ for f, v in self.flags.items() if v]) + ']')
|
||||
s.append('traps=[' + ', '.join([t.__name__ for t, v in self.traps.items() if v]) + ']')
|
||||
s.append(
|
||||
'Context(prec=%(prec)d, rounding=%(rounding)s, Emin=%(Emin)d, Emax=%(Emax)d, capitals=%(capitals)d'
|
||||
% vars(self))
|
||||
s.append('flags=[' + ', '.join([f.__name__ for f, v
|
||||
in self.flags.items() if v]) + ']')
|
||||
s.append('traps=[' + ', '.join([t.__name__ for t, v
|
||||
in self.traps.items() if v]) + ']')
|
||||
return ', '.join(s) + ')'
|
||||
|
||||
def get_manager(self):
|
||||
|
@ -2265,9 +2281,10 @@ class Context(object):
|
|||
|
||||
def copy(self):
|
||||
"""Returns a deep copy from self."""
|
||||
nc = Context(self.prec, self.rounding, self.traps.copy(), self.flags.copy(),
|
||||
self._rounding_decision, self.Emin, self.Emax,
|
||||
self.capitals, self._clamp, self._ignored_flags)
|
||||
nc = Context(self.prec, self.rounding, self.traps.copy(),
|
||||
self.flags.copy(), self._rounding_decision,
|
||||
self.Emin, self.Emax, self.capitals,
|
||||
self._clamp, self._ignored_flags)
|
||||
return nc
|
||||
__copy__ = copy
|
||||
|
||||
|
@ -2314,7 +2331,7 @@ class Context(object):
|
|||
def __hash__(self):
|
||||
"""A Context cannot be hashed."""
|
||||
# We inherit object.__hash__, so we must deny this explicitly
|
||||
raise TypeError, "Cannot hash a Context."
|
||||
raise TypeError("Cannot hash a Context.")
|
||||
|
||||
def Etiny(self):
|
||||
"""Returns Etiny (= Emin - prec + 1)"""
|
||||
|
@ -2340,7 +2357,6 @@ class Context(object):
|
|||
|
||||
This will make it not round for that operation.
|
||||
"""
|
||||
|
||||
rounding = self._rounding_decision
|
||||
self._rounding_decision = type
|
||||
return rounding
|
||||
|
@ -2528,10 +2544,10 @@ class Context(object):
|
|||
def multiply(self, a, b):
|
||||
"""multiply multiplies two operands.
|
||||
|
||||
If either operand is a special value then the general rules apply.
|
||||
Otherwise, the operands are multiplied together ('long multiplication'),
|
||||
resulting in a number which may be as long as the sum of the lengths
|
||||
of the two operands.
|
||||
If either operand is a special value then the general rules
|
||||
apply. Otherwise, the operands are multiplied together
|
||||
('long multiplication'), resulting in a number which may be
|
||||
as long as the sum of the lengths of the two operands.
|
||||
|
||||
>>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3'))
|
||||
Decimal("3.60")
|
||||
|
@ -2592,8 +2608,8 @@ class Context(object):
|
|||
1) before use.
|
||||
|
||||
If the increased precision needed for the intermediate calculations
|
||||
exceeds the capabilities of the implementation then an Invalid operation
|
||||
condition is raised.
|
||||
exceeds the capabilities of the implementation then an Invalid
|
||||
operation condition is raised.
|
||||
|
||||
If, when raising to a negative power, an underflow occurs during the
|
||||
division into 1, the operation is not halted at that point but
|
||||
|
@ -2631,7 +2647,7 @@ class Context(object):
|
|||
return a.__pow__(b, modulo, context=self)
|
||||
|
||||
def quantize(self, a, b):
|
||||
"""Returns a value equal to 'a' (rounded) and having the exponent of 'b'.
|
||||
"""Returns a value equal to 'a' (rounded), having the exponent of 'b'.
|
||||
|
||||
The coefficient of the result is derived from that of the left-hand
|
||||
operand. It may be rounded using the current rounding setting (if the
|
||||
|
@ -2641,8 +2657,8 @@ class Context(object):
|
|||
|
||||
Unlike other operations, if the length of the coefficient after the
|
||||
quantize operation would be greater than precision then an Invalid
|
||||
operation condition is raised. This guarantees that, unless there is an
|
||||
error condition, the exponent of the result of a quantize is always
|
||||
operation condition is raised. This guarantees that, unless there is
|
||||
an error condition, the exponent of the result of a quantize is always
|
||||
equal to that of the right-hand operand.
|
||||
|
||||
Also unlike other operations, quantize will never raise Underflow, even
|
||||
|
@ -2685,9 +2701,9 @@ class Context(object):
|
|||
"""Returns the remainder from integer division.
|
||||
|
||||
The result is the residue of the dividend after the operation of
|
||||
calculating integer division as described for divide-integer, rounded to
|
||||
precision digits if necessary. The sign of the result, if non-zero, is
|
||||
the same as that of the original dividend.
|
||||
calculating integer division as described for divide-integer, rounded
|
||||
to precision digits if necessary. The sign of the result, if non-zero,
|
||||
is the same as that of the original dividend.
|
||||
|
||||
This operation will fail under the same conditions as integer division
|
||||
(that is, if integer division on the same two operands would fail, the
|
||||
|
@ -2753,7 +2769,7 @@ class Context(object):
|
|||
return a.same_quantum(b)
|
||||
|
||||
def sqrt(self, a):
|
||||
"""Returns the square root of a non-negative number to context precision.
|
||||
"""Square root of a non-negative number to context precision.
|
||||
|
||||
If the result must be inexact, it is rounded using the round-half-even
|
||||
algorithm.
|
||||
|
@ -2835,6 +2851,7 @@ class Context(object):
|
|||
"""
|
||||
return a.to_integral(context=self)
|
||||
|
||||
|
||||
class _WorkRep(object):
|
||||
__slots__ = ('sign','int','exp')
|
||||
# sign: 0 or 1
|
||||
|
@ -2889,9 +2906,9 @@ def _normalize(op1, op2, shouldround = 0, prec = 0):
|
|||
other_len = len(str(other.int))
|
||||
if numdigits > (other_len + prec + 1 - tmp_len):
|
||||
# If the difference in adjusted exps is > prec+1, we know
|
||||
# other is insignificant, so might as well put a 1 after the precision.
|
||||
# (since this is only for addition.) Also stops use of massive longs.
|
||||
|
||||
# other is insignificant, so might as well put a 1 after the
|
||||
# precision (since this is only for addition). Also stops
|
||||
# use of massive longs.
|
||||
extend = prec + 2 - tmp_len
|
||||
if extend <= 0:
|
||||
extend = 1
|
||||
|
@ -2927,7 +2944,8 @@ def _adjust_coefficients(op1, op2):
|
|||
|
||||
return op1, op2, adjust
|
||||
|
||||
##### Helper Functions ########################################
|
||||
|
||||
##### Helper Functions #######################################################
|
||||
|
||||
def _convert_other(other):
|
||||
"""Convert other to Decimal.
|
||||
|
@ -2987,7 +3005,7 @@ def _isnan(num):
|
|||
return 0
|
||||
|
||||
|
||||
##### Setup Specific Contexts ################################
|
||||
##### Setup Specific Contexts ################################################
|
||||
|
||||
# The default context prototype used by Context()
|
||||
# Is mutable, so that new contexts can have different default values
|
||||
|
@ -3020,7 +3038,7 @@ ExtendedContext = Context(
|
|||
)
|
||||
|
||||
|
||||
##### Useful Constants (internal use only) ####################
|
||||
##### Useful Constants (internal use only) ###################################
|
||||
|
||||
# Reusable defaults
|
||||
Inf = Decimal('Inf')
|
||||
|
@ -3032,7 +3050,7 @@ Infsign = (Inf, negInf)
|
|||
NaN = Decimal('NaN')
|
||||
|
||||
|
||||
##### crud for parsing strings #################################
|
||||
##### crud for parsing strings ################################################
|
||||
import re
|
||||
|
||||
# There's an optional sign at the start, and an optional exponent
|
||||
|
@ -3052,13 +3070,16 @@ _parser = re.compile(r"""
|
|||
([eE](?P<exp>[-+]? \d+))?
|
||||
# \s*
|
||||
$
|
||||
""", re.VERBOSE).match #Uncomment the \s* to allow leading or trailing spaces.
|
||||
""", re.VERBOSE).match # Uncomment the \s* to allow leading/trailing spaces
|
||||
|
||||
del re
|
||||
|
||||
# return sign, n, p s.t. float string value == -1**sign * n * 10**p exactly
|
||||
|
||||
def _string2exact(s):
|
||||
"""Return sign, n, p s.t.
|
||||
|
||||
Float string value == -1**sign * n * 10**p exactly
|
||||
"""
|
||||
m = _parser(s)
|
||||
if m is None:
|
||||
raise ValueError("invalid literal for Decimal: %r" % s)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue