Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
C
cpython
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
cpython
Commits
ac4ae4ba
Kaydet (Commit)
ac4ae4ba
authored
Tem 18, 2006
tarafından
Facundo Batista
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Comments and docs cleanups, and some little fixes, provided by Santiágo Peresón
üst
caebe220
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
168 additions
and
147 deletions
+168
-147
decimal.py
Lib/decimal.py
+168
-147
No files found.
Lib/decimal.py
Dosyayı görüntüle @
ac4ae4ba
...
@@ -29,8 +29,8 @@ and IEEE standard 854-1987:
...
@@ -29,8 +29,8 @@ and IEEE standard 854-1987:
Decimal floating point has finite precision with arbitrarily large bounds.
Decimal floating point has finite precision with arbitrarily large bounds.
The purpose of th
e
module is to support arithmetic using familiar
The purpose of th
is
module is to support arithmetic using familiar
"schoolhouse" rules and to avoid
the some of
tricky representation
"schoolhouse" rules and to avoid
some of the
tricky representation
issues associated with binary floating point. The package is especially
issues associated with binary floating point. The package is especially
useful for financial applications or for contexts where users have
useful for financial applications or for contexts where users have
expectations that are at odds with binary floating point (for instance,
expectations that are at odds with binary floating point (for instance,
...
@@ -136,7 +136,7 @@ __all__ = [
...
@@ -136,7 +136,7 @@ __all__ = [
import
copy
as
_copy
import
copy
as
_copy
#Rounding
#
Rounding
ROUND_DOWN
=
'ROUND_DOWN'
ROUND_DOWN
=
'ROUND_DOWN'
ROUND_HALF_UP
=
'ROUND_HALF_UP'
ROUND_HALF_UP
=
'ROUND_HALF_UP'
ROUND_HALF_EVEN
=
'ROUND_HALF_EVEN'
ROUND_HALF_EVEN
=
'ROUND_HALF_EVEN'
...
@@ -145,11 +145,11 @@ ROUND_FLOOR = 'ROUND_FLOOR'
...
@@ -145,11 +145,11 @@ ROUND_FLOOR = 'ROUND_FLOOR'
ROUND_UP
=
'ROUND_UP'
ROUND_UP
=
'ROUND_UP'
ROUND_HALF_DOWN
=
'ROUND_HALF_DOWN'
ROUND_HALF_DOWN
=
'ROUND_HALF_DOWN'
#Rounding decision (not part of the public API)
#
Rounding decision (not part of the public API)
NEVER_ROUND
=
'NEVER_ROUND'
# Round in division (non-divmod), sqrt ONLY
NEVER_ROUND
=
'NEVER_ROUND'
# Round in division (non-divmod), sqrt ONLY
ALWAYS_ROUND
=
'ALWAYS_ROUND'
# Every operation rounds at end.
ALWAYS_ROUND
=
'ALWAYS_ROUND'
# Every operation rounds at end.
#Errors
#
Errors
class
DecimalException
(
ArithmeticError
):
class
DecimalException
(
ArithmeticError
):
"""Base exception class.
"""Base exception class.
...
@@ -160,17 +160,17 @@ class DecimalException(ArithmeticError):
...
@@ -160,17 +160,17 @@ class DecimalException(ArithmeticError):
called if the others are present. This isn't actually used for
called if the others are present. This isn't actually used for
anything, though.
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
To define a new exception, it should be sufficient to have it derive
from DecimalException.
from DecimalException.
"""
"""
def
handle
(
self
,
context
,
*
args
):
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
pass
...
@@ -185,6 +185,7 @@ class Clamped(DecimalException):
...
@@ -185,6 +185,7 @@ class Clamped(DecimalException):
this latter case, the exponent is reduced to fit and the corresponding
this latter case, the exponent is reduced to fit and the corresponding
number of zero digits are appended to the coefficient ("fold-down").
number of zero digits are appended to the coefficient ("fold-down").
"""
"""
pass
class
InvalidOperation
(
DecimalException
):
class
InvalidOperation
(
DecimalException
):
...
@@ -207,10 +208,11 @@ class InvalidOperation(DecimalException):
...
@@ -207,10 +208,11 @@ class InvalidOperation(DecimalException):
"""
"""
def
handle
(
self
,
context
,
*
args
):
def
handle
(
self
,
context
,
*
args
):
if
args
:
if
args
:
if
args
[
0
]
==
1
:
#
sNaN, must drop 's' but keep diagnostics
if
args
[
0
]
==
1
:
#
sNaN, must drop 's' but keep diagnostics
return
Decimal
(
(
args
[
1
]
.
_sign
,
args
[
1
]
.
_int
,
'n'
)
)
return
Decimal
(
(
args
[
1
]
.
_sign
,
args
[
1
]
.
_int
,
'n'
)
)
return
NaN
return
NaN
class
ConversionSyntax
(
InvalidOperation
):
class
ConversionSyntax
(
InvalidOperation
):
"""Trying to convert badly formed string.
"""Trying to convert badly formed string.
...
@@ -218,9 +220,9 @@ class ConversionSyntax(InvalidOperation):
...
@@ -218,9 +220,9 @@ class ConversionSyntax(InvalidOperation):
converted to a number and it does not conform to the numeric string
converted to a number and it does not conform to the numeric string
syntax. The result is [0,qNaN].
syntax. The result is [0,qNaN].
"""
"""
def
handle
(
self
,
context
,
*
args
):
def
handle
(
self
,
context
,
*
args
):
return
(
0
,
(
0
,),
'n'
)
#Passed to something which uses a tuple.
return
(
0
,
(
0
,),
'n'
)
# Passed to something which uses a tuple.
class
DivisionByZero
(
DecimalException
,
ZeroDivisionError
):
class
DivisionByZero
(
DecimalException
,
ZeroDivisionError
):
"""Division by 0.
"""Division by 0.
...
@@ -234,12 +236,12 @@ class DivisionByZero(DecimalException, ZeroDivisionError):
...
@@ -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
or of the signs of the operands for divide, or is 1 for an odd power of
-0, for power.
-0, for power.
"""
"""
def
handle
(
self
,
context
,
sign
,
double
=
None
,
*
args
):
def
handle
(
self
,
context
,
sign
,
double
=
None
,
*
args
):
if
double
is
not
None
:
if
double
is
not
None
:
return
(
Infsign
[
sign
],)
*
2
return
(
Infsign
[
sign
],)
*
2
return
Infsign
[
sign
]
return
Infsign
[
sign
]
class
DivisionImpossible
(
InvalidOperation
):
class
DivisionImpossible
(
InvalidOperation
):
"""Cannot perform the division adequately.
"""Cannot perform the division adequately.
...
@@ -247,10 +249,10 @@ class DivisionImpossible(InvalidOperation):
...
@@ -247,10 +249,10 @@ class DivisionImpossible(InvalidOperation):
divide-integer or remainder operation had too many digits (would be
divide-integer or remainder operation had too many digits (would be
longer than precision). The result is [0,qNaN].
longer than precision). The result is [0,qNaN].
"""
"""
def
handle
(
self
,
context
,
*
args
):
def
handle
(
self
,
context
,
*
args
):
return
(
NaN
,
NaN
)
return
(
NaN
,
NaN
)
class
DivisionUndefined
(
InvalidOperation
,
ZeroDivisionError
):
class
DivisionUndefined
(
InvalidOperation
,
ZeroDivisionError
):
"""Undefined result of division.
"""Undefined result of division.
...
@@ -258,12 +260,12 @@ class DivisionUndefined(InvalidOperation, ZeroDivisionError):
...
@@ -258,12 +260,12 @@ class DivisionUndefined(InvalidOperation, ZeroDivisionError):
attempted (during a divide-integer, divide, or remainder operation), and
attempted (during a divide-integer, divide, or remainder operation), and
the dividend is also zero. The result is [0,qNaN].
the dividend is also zero. The result is [0,qNaN].
"""
"""
def
handle
(
self
,
context
,
tup
=
None
,
*
args
):
def
handle
(
self
,
context
,
tup
=
None
,
*
args
):
if
tup
is
not
None
:
if
tup
is
not
None
:
return
(
NaN
,
NaN
)
#f
or 0 %0, 0 // 0
return
(
NaN
,
NaN
)
# F
or 0 %0, 0 // 0
return
NaN
return
NaN
class
Inexact
(
DecimalException
):
class
Inexact
(
DecimalException
):
"""Had to round, losing information.
"""Had to round, losing information.
...
@@ -277,6 +279,7 @@ class Inexact(DecimalException):
...
@@ -277,6 +279,7 @@ class Inexact(DecimalException):
"""
"""
pass
pass
class
InvalidContext
(
InvalidOperation
):
class
InvalidContext
(
InvalidOperation
):
"""Invalid context. Unknown rounding, for example.
"""Invalid context. Unknown rounding, for example.
...
@@ -287,10 +290,10 @@ class InvalidContext(InvalidOperation):
...
@@ -287,10 +290,10 @@ class InvalidContext(InvalidOperation):
was specified. These aspects of the context need only be checked when
was specified. These aspects of the context need only be checked when
the values are required to be used. The result is [0,qNaN].
the values are required to be used. The result is [0,qNaN].
"""
"""
def
handle
(
self
,
context
,
*
args
):
def
handle
(
self
,
context
,
*
args
):
return
NaN
return
NaN
class
Rounded
(
DecimalException
):
class
Rounded
(
DecimalException
):
"""Number got rounded (not necessarily changed during rounding).
"""Number got rounded (not necessarily changed during rounding).
...
@@ -304,6 +307,7 @@ class Rounded(DecimalException):
...
@@ -304,6 +307,7 @@ class Rounded(DecimalException):
"""
"""
pass
pass
class
Subnormal
(
DecimalException
):
class
Subnormal
(
DecimalException
):
"""Exponent < Emin before rounding.
"""Exponent < Emin before rounding.
...
@@ -316,6 +320,7 @@ class Subnormal(DecimalException):
...
@@ -316,6 +320,7 @@ class Subnormal(DecimalException):
"""
"""
pass
pass
class
Overflow
(
Inexact
,
Rounded
):
class
Overflow
(
Inexact
,
Rounded
):
"""Numerical overflow.
"""Numerical overflow.
...
@@ -337,7 +342,6 @@ class Overflow(Inexact, Rounded):
...
@@ -337,7 +342,6 @@ class Overflow(Inexact, Rounded):
result is 0, or is [1,inf] otherwise. In all cases, Inexact and Rounded
result is 0, or is [1,inf] otherwise. In all cases, Inexact and Rounded
will also be raised.
will also be raised.
"""
"""
def
handle
(
self
,
context
,
sign
,
*
args
):
def
handle
(
self
,
context
,
sign
,
*
args
):
if
context
.
rounding
in
(
ROUND_HALF_UP
,
ROUND_HALF_EVEN
,
if
context
.
rounding
in
(
ROUND_HALF_UP
,
ROUND_HALF_EVEN
,
ROUND_HALF_DOWN
,
ROUND_UP
):
ROUND_HALF_DOWN
,
ROUND_UP
):
...
@@ -368,6 +372,8 @@ class Underflow(Inexact, Rounded, Subnormal):
...
@@ -368,6 +372,8 @@ class Underflow(Inexact, Rounded, Subnormal):
In all cases, Inexact, Rounded, and Subnormal will also be raised.
In all cases, Inexact, Rounded, and Subnormal will also be raised.
"""
"""
pass
# List of public traps and flags
# List of public traps and flags
_signals
=
[
Clamped
,
DivisionByZero
,
Inexact
,
Overflow
,
Rounded
,
_signals
=
[
Clamped
,
DivisionByZero
,
Inexact
,
Overflow
,
Rounded
,
...
@@ -379,32 +385,34 @@ _condition_map = {ConversionSyntax:InvalidOperation,
...
@@ -379,32 +385,34 @@ _condition_map = {ConversionSyntax:InvalidOperation,
DivisionUndefined
:
InvalidOperation
,
DivisionUndefined
:
InvalidOperation
,
InvalidContext
:
InvalidOperation
}
InvalidContext
:
InvalidOperation
}
##### Context Functions #######################################
##### Context Functions #######################################
##############
# The getcontext() and setcontext() function manage access to a thread-local
# The getcontext() and setcontext() function manage access to a thread-local
# current context. Py2.4 offers direct support for thread locals. If that
# current context. Py2.4 offers direct support for thread locals. If that
# is not available, use threading.currentThread() which is slower but will
# 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
# 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
:
try
:
import
threading
import
threading
except
ImportError
:
except
ImportError
:
# Python was compiled without threads; create a mock object instead
# Python was compiled without threads; create a mock object instead
import
sys
import
sys
class
MockThreading
:
class
MockThreading
(
object
)
:
def
local
(
self
,
sys
=
sys
):
def
local
(
self
,
sys
=
sys
):
return
sys
.
modules
[
__name__
]
return
sys
.
modules
[
__name__
]
threading
=
MockThreading
()
threading
=
MockThreading
()
del
sys
,
MockThreading
del
sys
,
MockThreading
try
:
try
:
threading
.
local
threading
.
local
except
AttributeError
:
except
AttributeError
:
#To fix reloading, force it to create a new context
#
To fix reloading, force it to create a new context
#Old contexts have different exceptions in their dicts, making problems.
#
Old contexts have different exceptions in their dicts, making problems.
if
hasattr
(
threading
.
currentThread
(),
'__decimal_context__'
):
if
hasattr
(
threading
.
currentThread
(),
'__decimal_context__'
):
del
threading
.
currentThread
()
.
__decimal_context__
del
threading
.
currentThread
()
.
__decimal_context__
...
@@ -459,7 +467,7 @@ else:
...
@@ -459,7 +467,7 @@ else:
del
threading
,
local
# Don't contaminate the namespace
del
threading
,
local
# Don't contaminate the namespace
##### Decimal class ###########################################
##### Decimal class ###########################################
###############
class
Decimal
(
object
):
class
Decimal
(
object
):
"""Floating point class for decimal arithmetic."""
"""Floating point class for decimal arithmetic."""
...
@@ -475,7 +483,7 @@ class Decimal(object):
...
@@ -475,7 +483,7 @@ class Decimal(object):
>>> Decimal('3.14') # string input
>>> Decimal('3.14') # string input
Decimal("3.14")
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("3.14")
>>> Decimal(314) # int or long
>>> Decimal(314) # int or long
Decimal("314")
Decimal("314")
...
@@ -514,12 +522,13 @@ class Decimal(object):
...
@@ -514,12 +522,13 @@ class Decimal(object):
# tuple/list conversion (possibly from as_tuple())
# tuple/list conversion (possibly from as_tuple())
if
isinstance
(
value
,
(
list
,
tuple
)):
if
isinstance
(
value
,
(
list
,
tuple
)):
if
len
(
value
)
!=
3
:
if
len
(
value
)
!=
3
:
raise
ValueError
,
'Invalid arguments'
raise
ValueError
(
'Invalid arguments'
)
if
value
[
0
]
not
in
(
0
,
1
):
if
value
[
0
]
not
in
(
0
,
1
):
raise
ValueError
,
'Invalid sign'
raise
ValueError
(
'Invalid sign'
)
for
digit
in
value
[
1
]:
for
digit
in
value
[
1
]:
if
not
isinstance
(
digit
,
(
int
,
long
))
or
digit
<
0
:
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
.
_sign
=
value
[
0
]
self
.
_int
=
tuple
(
value
[
1
])
self
.
_int
=
tuple
(
value
[
1
])
...
@@ -553,22 +562,23 @@ class Decimal(object):
...
@@ -553,22 +562,23 @@ class Decimal(object):
if
_isnan
(
value
):
if
_isnan
(
value
):
sig
,
sign
,
diag
=
_isnan
(
value
)
sig
,
sign
,
diag
=
_isnan
(
value
)
self
.
_is_special
=
True
self
.
_is_special
=
True
if
len
(
diag
)
>
context
.
prec
:
#
Diagnostic info too long
if
len
(
diag
)
>
context
.
prec
:
#
Diagnostic info too long
self
.
_sign
,
self
.
_int
,
self
.
_exp
=
\
self
.
_sign
,
self
.
_int
,
self
.
_exp
=
\
context
.
_raise_error
(
ConversionSyntax
)
context
.
_raise_error
(
ConversionSyntax
)
return
self
return
self
if
sig
==
1
:
if
sig
==
1
:
self
.
_exp
=
'n'
#qNaN
self
.
_exp
=
'n'
#qNaN
else
:
#
sig == 2
else
:
#
sig == 2
self
.
_exp
=
'N'
#sNaN
self
.
_exp
=
'N'
#sNaN
self
.
_sign
=
sign
self
.
_sign
=
sign
self
.
_int
=
tuple
(
map
(
int
,
diag
))
#
Diagnostic info
self
.
_int
=
tuple
(
map
(
int
,
diag
))
#
Diagnostic info
return
self
return
self
try
:
try
:
self
.
_sign
,
self
.
_int
,
self
.
_exp
=
_string2exact
(
value
)
self
.
_sign
,
self
.
_int
,
self
.
_exp
=
_string2exact
(
value
)
except
ValueError
:
except
ValueError
:
self
.
_is_special
=
True
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
return
self
raise
TypeError
(
"Cannot convert
%
r to Decimal"
%
value
)
raise
TypeError
(
"Cannot convert
%
r to Decimal"
%
value
)
...
@@ -657,9 +667,9 @@ class Decimal(object):
...
@@ -657,9 +667,9 @@ class Decimal(object):
return
cmp
(
self
.
_isinfinity
(),
other
.
_isinfinity
())
return
cmp
(
self
.
_isinfinity
(),
other
.
_isinfinity
())
if
not
self
and
not
other
:
if
not
self
and
not
other
:
return
0
#
If both 0, sign comparison isn't certain.
return
0
#
If both 0, sign comparison isn't certain.
#If different signs, neg one is less
#
If different signs, neg one is less
if
other
.
_sign
<
self
.
_sign
:
if
other
.
_sign
<
self
.
_sign
:
return
-
1
return
-
1
if
self
.
_sign
<
other
.
_sign
:
if
self
.
_sign
<
other
.
_sign
:
...
@@ -670,7 +680,7 @@ class Decimal(object):
...
@@ -670,7 +680,7 @@ class Decimal(object):
if
self_adjusted
==
other_adjusted
and
\
if
self_adjusted
==
other_adjusted
and
\
self
.
_int
+
(
0
,)
*
(
self
.
_exp
-
other
.
_exp
)
==
\
self
.
_int
+
(
0
,)
*
(
self
.
_exp
-
other
.
_exp
)
==
\
other
.
_int
+
(
0
,)
*
(
other
.
_exp
-
self
.
_exp
):
other
.
_int
+
(
0
,)
*
(
other
.
_exp
-
self
.
_exp
):
return
0
#e
qual, except in precision. ([0]*(-x) = [])
return
0
# E
qual, except in precision. ([0]*(-x) = [])
elif
self_adjusted
>
other_adjusted
and
self
.
_int
[
0
]
!=
0
:
elif
self_adjusted
>
other_adjusted
and
self
.
_int
[
0
]
!=
0
:
return
(
-
1
)
**
self
.
_sign
return
(
-
1
)
**
self
.
_sign
elif
self_adjusted
<
other_adjusted
and
other
.
_int
[
0
]
!=
0
:
elif
self_adjusted
<
other_adjusted
and
other
.
_int
[
0
]
!=
0
:
...
@@ -681,7 +691,7 @@ class Decimal(object):
...
@@ -681,7 +691,7 @@ class Decimal(object):
context
=
getcontext
()
context
=
getcontext
()
context
=
context
.
_shallow_copy
()
context
=
context
.
_shallow_copy
()
rounding
=
context
.
_set_rounding
(
ROUND_UP
)
#r
ound away from 0
rounding
=
context
.
_set_rounding
(
ROUND_UP
)
# R
ound away from 0
flags
=
context
.
_ignore_all_flags
()
flags
=
context
.
_ignore_all_flags
()
res
=
self
.
__sub__
(
other
,
context
=
context
)
res
=
self
.
__sub__
(
other
,
context
=
context
)
...
@@ -719,7 +729,7 @@ class Decimal(object):
...
@@ -719,7 +729,7 @@ class Decimal(object):
if
other
is
NotImplemented
:
if
other
is
NotImplemented
:
return
other
return
other
#
c
ompare(NaN, NaN) = NaN
#
C
ompare(NaN, NaN) = NaN
if
(
self
.
_is_special
or
other
and
other
.
_is_special
):
if
(
self
.
_is_special
or
other
and
other
.
_is_special
):
ans
=
self
.
_check_nans
(
other
,
context
)
ans
=
self
.
_check_nans
(
other
,
context
)
if
ans
:
if
ans
:
...
@@ -780,11 +790,11 @@ class Decimal(object):
...
@@ -780,11 +790,11 @@ class Decimal(object):
tmp
=
map
(
str
,
self
.
_int
)
tmp
=
map
(
str
,
self
.
_int
)
numdigits
=
len
(
self
.
_int
)
numdigits
=
len
(
self
.
_int
)
leftdigits
=
self
.
_exp
+
numdigits
leftdigits
=
self
.
_exp
+
numdigits
if
eng
and
not
self
:
#
self = 0eX wants 0[.0[0]]eY, not [[0]0]0eY
if
eng
and
not
self
:
#
self = 0eX wants 0[.0[0]]eY, not [[0]0]0eY
if
self
.
_exp
<
0
and
self
.
_exp
>=
-
6
:
#
short, no need for e/E
if
self
.
_exp
<
0
and
self
.
_exp
>=
-
6
:
#
short, no need for e/E
s
=
'-'
*
self
.
_sign
+
'0.'
+
'0'
*
(
abs
(
self
.
_exp
))
s
=
'-'
*
self
.
_sign
+
'0.'
+
'0'
*
(
abs
(
self
.
_exp
))
return
s
return
s
#exp is closest mult. of 3 >= self._exp
#
exp is closest mult. of 3 >= self._exp
exp
=
((
self
.
_exp
-
1
)
//
3
+
1
)
*
3
exp
=
((
self
.
_exp
-
1
)
//
3
+
1
)
*
3
if
exp
!=
self
.
_exp
:
if
exp
!=
self
.
_exp
:
s
=
'0.'
+
'0'
*
(
exp
-
self
.
_exp
)
s
=
'0.'
+
'0'
*
(
exp
-
self
.
_exp
)
...
@@ -796,7 +806,7 @@ class Decimal(object):
...
@@ -796,7 +806,7 @@ class Decimal(object):
else
:
else
:
s
+=
'e'
s
+=
'e'
if
exp
>
0
:
if
exp
>
0
:
s
+=
'+'
#
0.0e+3, not 0.0e3
s
+=
'+'
#
0.0e+3, not 0.0e3
s
+=
str
(
exp
)
s
+=
str
(
exp
)
s
=
'-'
*
self
.
_sign
+
s
s
=
'-'
*
self
.
_sign
+
s
return
s
return
s
...
@@ -936,19 +946,19 @@ class Decimal(object):
...
@@ -936,19 +946,19 @@ class Decimal(object):
return
ans
return
ans
if
self
.
_isinfinity
():
if
self
.
_isinfinity
():
#If both INF, same sign => same as both, opposite => error.
#
If both INF, same sign => same as both, opposite => error.
if
self
.
_sign
!=
other
.
_sign
and
other
.
_isinfinity
():
if
self
.
_sign
!=
other
.
_sign
and
other
.
_isinfinity
():
return
context
.
_raise_error
(
InvalidOperation
,
'-INF + INF'
)
return
context
.
_raise_error
(
InvalidOperation
,
'-INF + INF'
)
return
Decimal
(
self
)
return
Decimal
(
self
)
if
other
.
_isinfinity
():
if
other
.
_isinfinity
():
return
Decimal
(
other
)
#Can't both be infinity here
return
Decimal
(
other
)
#
Can't both be infinity here
shouldround
=
context
.
_rounding_decision
==
ALWAYS_ROUND
shouldround
=
context
.
_rounding_decision
==
ALWAYS_ROUND
exp
=
min
(
self
.
_exp
,
other
.
_exp
)
exp
=
min
(
self
.
_exp
,
other
.
_exp
)
negativezero
=
0
negativezero
=
0
if
context
.
rounding
==
ROUND_FLOOR
and
self
.
_sign
!=
other
.
_sign
:
if
context
.
rounding
==
ROUND_FLOOR
and
self
.
_sign
!=
other
.
_sign
:
#If the answer is 0, the sign should be negative, in this case.
#
If the answer is 0, the sign should be negative, in this case.
negativezero
=
1
negativezero
=
1
if
not
self
and
not
other
:
if
not
self
and
not
other
:
...
@@ -983,19 +993,19 @@ class Decimal(object):
...
@@ -983,19 +993,19 @@ class Decimal(object):
return
Decimal
((
negativezero
,
(
0
,),
exp
))
return
Decimal
((
negativezero
,
(
0
,),
exp
))
if
op1
.
int
<
op2
.
int
:
if
op1
.
int
<
op2
.
int
:
op1
,
op2
=
op2
,
op1
op1
,
op2
=
op2
,
op1
#OK, now abs(op1) > abs(op2)
#
OK, now abs(op1) > abs(op2)
if
op1
.
sign
==
1
:
if
op1
.
sign
==
1
:
result
.
sign
=
1
result
.
sign
=
1
op1
.
sign
,
op2
.
sign
=
op2
.
sign
,
op1
.
sign
op1
.
sign
,
op2
.
sign
=
op2
.
sign
,
op1
.
sign
else
:
else
:
result
.
sign
=
0
result
.
sign
=
0
#So we know the sign, and op1 > 0.
#
So we know the sign, and op1 > 0.
elif
op1
.
sign
==
1
:
elif
op1
.
sign
==
1
:
result
.
sign
=
1
result
.
sign
=
1
op1
.
sign
,
op2
.
sign
=
(
0
,
0
)
op1
.
sign
,
op2
.
sign
=
(
0
,
0
)
else
:
else
:
result
.
sign
=
0
result
.
sign
=
0
#Now, op1 > abs(op2) > 0
#
Now, op1 > abs(op2) > 0
if
op2
.
sign
==
0
:
if
op2
.
sign
==
0
:
result
.
int
=
op1
.
int
+
op2
.
int
result
.
int
=
op1
.
int
+
op2
.
int
...
@@ -1052,8 +1062,8 @@ class Decimal(object):
...
@@ -1052,8 +1062,8 @@ class Decimal(object):
ans
=
self
.
_check_nans
(
context
=
context
)
ans
=
self
.
_check_nans
(
context
=
context
)
if
ans
:
if
ans
:
return
ans
return
ans
# Must be infinite, and incrementing makes no difference
return
Decimal
(
self
)
# Must be infinite, and incrementing makes no difference
return
Decimal
(
self
)
L
=
list
(
self
.
_int
)
L
=
list
(
self
.
_int
)
L
[
-
1
]
+=
1
L
[
-
1
]
+=
1
...
@@ -1109,7 +1119,7 @@ class Decimal(object):
...
@@ -1109,7 +1119,7 @@ class Decimal(object):
if
not
self
or
not
other
:
if
not
self
or
not
other
:
ans
=
Decimal
((
resultsign
,
(
0
,),
resultexp
))
ans
=
Decimal
((
resultsign
,
(
0
,),
resultexp
))
if
shouldround
:
if
shouldround
:
#Fixing in case the exponent is out of bounds
#
Fixing in case the exponent is out of bounds
ans
=
ans
.
_fix
(
context
)
ans
=
ans
.
_fix
(
context
)
return
ans
return
ans
...
@@ -1128,7 +1138,7 @@ class Decimal(object):
...
@@ -1128,7 +1138,7 @@ class Decimal(object):
op1
=
_WorkRep
(
self
)
op1
=
_WorkRep
(
self
)
op2
=
_WorkRep
(
other
)
op2
=
_WorkRep
(
other
)
ans
=
Decimal
(
(
resultsign
,
map
(
int
,
str
(
op1
.
int
*
op2
.
int
)),
resultexp
))
ans
=
Decimal
((
resultsign
,
map
(
int
,
str
(
op1
.
int
*
op2
.
int
)),
resultexp
))
if
shouldround
:
if
shouldround
:
ans
=
ans
.
_fix
(
context
)
ans
=
ans
.
_fix
(
context
)
...
@@ -1221,12 +1231,11 @@ class Decimal(object):
...
@@ -1221,12 +1231,11 @@ class Decimal(object):
sign
,
1
)
sign
,
1
)
return
context
.
_raise_error
(
DivisionByZero
,
'x / 0'
,
sign
)
return
context
.
_raise_error
(
DivisionByZero
,
'x / 0'
,
sign
)
#OK, so neither = 0, INF or NaN
# OK, so neither = 0, INF or NaN
shouldround
=
context
.
_rounding_decision
==
ALWAYS_ROUND
shouldround
=
context
.
_rounding_decision
==
ALWAYS_ROUND
#If we're dividing into ints, and self < other, stop.
#
If we're dividing into ints, and self < other, stop.
#self.__abs__(0) does not round.
#
self.__abs__(0) does not round.
if
divmod
and
(
self
.
__abs__
(
0
,
context
)
<
other
.
__abs__
(
0
,
context
)):
if
divmod
and
(
self
.
__abs__
(
0
,
context
)
<
other
.
__abs__
(
0
,
context
)):
if
divmod
==
1
or
divmod
==
3
:
if
divmod
==
1
or
divmod
==
3
:
...
@@ -1238,7 +1247,7 @@ class Decimal(object):
...
@@ -1238,7 +1247,7 @@ class Decimal(object):
ans2
)
ans2
)
elif
divmod
==
2
:
elif
divmod
==
2
:
#Don't round the mod part, if we don't need it.
#
Don't round the mod part, if we don't need it.
return
(
Decimal
(
(
sign
,
(
0
,),
0
)
),
Decimal
(
self
))
return
(
Decimal
(
(
sign
,
(
0
,),
0
)
),
Decimal
(
self
))
op1
=
_WorkRep
(
self
)
op1
=
_WorkRep
(
self
)
...
@@ -1287,7 +1296,7 @@ class Decimal(object):
...
@@ -1287,7 +1296,7 @@ class Decimal(object):
op1
.
exp
-=
1
op1
.
exp
-=
1
if
res
.
exp
==
0
and
divmod
and
op2
.
int
>
op1
.
int
:
if
res
.
exp
==
0
and
divmod
and
op2
.
int
>
op1
.
int
:
#Solves an error in precision. Same as a previous block.
#
Solves an error in precision. Same as a previous block.
if
res
.
int
>=
prec_limit
and
shouldround
:
if
res
.
int
>=
prec_limit
and
shouldround
:
return
context
.
_raise_error
(
DivisionImpossible
)
return
context
.
_raise_error
(
DivisionImpossible
)
...
@@ -1373,7 +1382,7 @@ class Decimal(object):
...
@@ -1373,7 +1382,7 @@ class Decimal(object):
# ignored in the calling function.
# ignored in the calling function.
context
=
context
.
_shallow_copy
()
context
=
context
.
_shallow_copy
()
flags
=
context
.
_ignore_flags
(
Rounded
,
Inexact
)
flags
=
context
.
_ignore_flags
(
Rounded
,
Inexact
)
#
k
eep DivisionImpossible flags
#
K
eep DivisionImpossible flags
(
side
,
r
)
=
self
.
__divmod__
(
other
,
context
=
context
)
(
side
,
r
)
=
self
.
__divmod__
(
other
,
context
=
context
)
if
r
.
_isnan
():
if
r
.
_isnan
():
...
@@ -1396,7 +1405,7 @@ class Decimal(object):
...
@@ -1396,7 +1405,7 @@ class Decimal(object):
if
r
<
comparison
:
if
r
<
comparison
:
r
.
_sign
,
comparison
.
_sign
=
s1
,
s2
r
.
_sign
,
comparison
.
_sign
=
s1
,
s2
#Get flags now
#
Get flags now
self
.
__divmod__
(
other
,
context
=
context
)
self
.
__divmod__
(
other
,
context
=
context
)
return
r
.
_fix
(
context
)
return
r
.
_fix
(
context
)
r
.
_sign
,
comparison
.
_sign
=
s1
,
s2
r
.
_sign
,
comparison
.
_sign
=
s1
,
s2
...
@@ -1418,7 +1427,8 @@ class Decimal(object):
...
@@ -1418,7 +1427,8 @@ class Decimal(object):
if
r
>
comparison
or
decrease
and
r
==
comparison
:
if
r
>
comparison
or
decrease
and
r
==
comparison
:
r
.
_sign
,
comparison
.
_sign
=
s1
,
s2
r
.
_sign
,
comparison
.
_sign
=
s1
,
s2
context
.
prec
+=
1
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
context
.
prec
-=
1
return
context
.
_raise_error
(
DivisionImpossible
)[
1
]
return
context
.
_raise_error
(
DivisionImpossible
)[
1
]
context
.
prec
-=
1
context
.
prec
-=
1
...
@@ -1453,7 +1463,7 @@ class Decimal(object):
...
@@ -1453,7 +1463,7 @@ class Decimal(object):
context
=
getcontext
()
context
=
getcontext
()
return
context
.
_raise_error
(
InvalidContext
)
return
context
.
_raise_error
(
InvalidContext
)
elif
self
.
_isinfinity
():
elif
self
.
_isinfinity
():
raise
OverflowError
,
"Cannot convert infinity to long"
raise
OverflowError
(
"Cannot convert infinity to long"
)
if
self
.
_exp
>=
0
:
if
self
.
_exp
>=
0
:
s
=
''
.
join
(
map
(
str
,
self
.
_int
))
+
'0'
*
self
.
_exp
s
=
''
.
join
(
map
(
str
,
self
.
_int
))
+
'0'
*
self
.
_exp
else
:
else
:
...
@@ -1507,13 +1517,13 @@ class Decimal(object):
...
@@ -1507,13 +1517,13 @@ class Decimal(object):
context
.
_raise_error
(
Clamped
)
context
.
_raise_error
(
Clamped
)
return
ans
return
ans
ans
=
ans
.
_rescale
(
Etiny
,
context
=
context
)
ans
=
ans
.
_rescale
(
Etiny
,
context
=
context
)
#It isn't zero, and exp < Emin => subnormal
#
It isn't zero, and exp < Emin => subnormal
context
.
_raise_error
(
Subnormal
)
context
.
_raise_error
(
Subnormal
)
if
context
.
flags
[
Inexact
]:
if
context
.
flags
[
Inexact
]:
context
.
_raise_error
(
Underflow
)
context
.
_raise_error
(
Underflow
)
else
:
else
:
if
ans
:
if
ans
:
#Only raise subnormal if non-zero.
#
Only raise subnormal if non-zero.
context
.
_raise_error
(
Subnormal
)
context
.
_raise_error
(
Subnormal
)
else
:
else
:
Etop
=
context
.
Etop
()
Etop
=
context
.
Etop
()
...
@@ -1530,7 +1540,8 @@ class Decimal(object):
...
@@ -1530,7 +1540,8 @@ class Decimal(object):
return
ans
return
ans
context
.
_raise_error
(
Inexact
)
context
.
_raise_error
(
Inexact
)
context
.
_raise_error
(
Rounded
)
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
return
ans
def
_round
(
self
,
prec
=
None
,
rounding
=
None
,
context
=
None
):
def
_round
(
self
,
prec
=
None
,
rounding
=
None
,
context
=
None
):
...
@@ -1590,18 +1601,18 @@ class Decimal(object):
...
@@ -1590,18 +1601,18 @@ class Decimal(object):
ans
=
Decimal
(
(
temp
.
_sign
,
tmp
,
temp
.
_exp
-
expdiff
))
ans
=
Decimal
(
(
temp
.
_sign
,
tmp
,
temp
.
_exp
-
expdiff
))
return
ans
return
ans
#OK, but maybe all the lost digits are 0.
#
OK, but maybe all the lost digits are 0.
lostdigits
=
self
.
_int
[
expdiff
:]
lostdigits
=
self
.
_int
[
expdiff
:]
if
lostdigits
==
(
0
,)
*
len
(
lostdigits
):
if
lostdigits
==
(
0
,)
*
len
(
lostdigits
):
ans
=
Decimal
(
(
temp
.
_sign
,
temp
.
_int
[:
prec
],
temp
.
_exp
-
expdiff
))
ans
=
Decimal
(
(
temp
.
_sign
,
temp
.
_int
[:
prec
],
temp
.
_exp
-
expdiff
))
#Rounded, but not Inexact
#
Rounded, but not Inexact
context
.
_raise_error
(
Rounded
)
context
.
_raise_error
(
Rounded
)
return
ans
return
ans
# Okay, let's round and lose data
# Okay, let's round and lose data
this_function
=
getattr
(
temp
,
self
.
_pick_rounding_function
[
rounding
])
this_function
=
getattr
(
temp
,
self
.
_pick_rounding_function
[
rounding
])
#Now we've got the rounding function
#
Now we've got the rounding function
if
prec
!=
context
.
prec
:
if
prec
!=
context
.
prec
:
context
=
context
.
_shallow_copy
()
context
=
context
.
_shallow_copy
()
...
@@ -1697,7 +1708,7 @@ class Decimal(object):
...
@@ -1697,7 +1708,7 @@ class Decimal(object):
context
=
getcontext
()
context
=
getcontext
()
if
self
.
_is_special
or
n
.
_is_special
or
n
.
adjusted
()
>
8
:
if
self
.
_is_special
or
n
.
_is_special
or
n
.
adjusted
()
>
8
:
#Because the spot << doesn't work with really big exponents
#
Because the spot << doesn't work with really big exponents
if
n
.
_isinfinity
()
or
n
.
adjusted
()
>
8
:
if
n
.
_isinfinity
()
or
n
.
adjusted
()
>
8
:
return
context
.
_raise_error
(
InvalidOperation
,
'x ** INF'
)
return
context
.
_raise_error
(
InvalidOperation
,
'x ** INF'
)
...
@@ -1727,10 +1738,9 @@ class Decimal(object):
...
@@ -1727,10 +1738,9 @@ class Decimal(object):
return
Infsign
[
sign
]
return
Infsign
[
sign
]
return
Decimal
(
(
sign
,
(
0
,),
0
)
)
return
Decimal
(
(
sign
,
(
0
,),
0
)
)
#with ludicrously large exponent, just raise an overflow and return inf.
# 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
\
if
not
modulo
and
n
>
0
\
and
self
:
and
(
self
.
_exp
+
len
(
self
.
_int
)
-
1
)
*
n
>
context
.
Emax
and
self
:
tmp
=
Decimal
(
'inf'
)
tmp
=
Decimal
(
'inf'
)
tmp
.
_sign
=
sign
tmp
.
_sign
=
sign
context
.
_raise_error
(
Rounded
)
context
.
_raise_error
(
Rounded
)
...
@@ -1749,7 +1759,7 @@ class Decimal(object):
...
@@ -1749,7 +1759,7 @@ class Decimal(object):
context
=
context
.
_shallow_copy
()
context
=
context
.
_shallow_copy
()
context
.
prec
=
firstprec
+
elength
+
1
context
.
prec
=
firstprec
+
elength
+
1
if
n
<
0
:
if
n
<
0
:
#n is a long now, not Decimal instance
#
n is a long now, not Decimal instance
n
=
-
n
n
=
-
n
mul
=
Decimal
(
1
)
.
__div__
(
mul
,
context
=
context
)
mul
=
Decimal
(
1
)
.
__div__
(
mul
,
context
=
context
)
...
@@ -1758,7 +1768,7 @@ class Decimal(object):
...
@@ -1758,7 +1768,7 @@ class Decimal(object):
spot
<<=
1
spot
<<=
1
spot
>>=
1
spot
>>=
1
#Spot is the highest power of 2 less than n
#
Spot is the highest power of 2 less than n
while
spot
:
while
spot
:
val
=
val
.
__mul__
(
val
,
context
=
context
)
val
=
val
.
__mul__
(
val
,
context
=
context
)
if
val
.
_isinfinity
():
if
val
.
_isinfinity
():
...
@@ -1816,7 +1826,7 @@ class Decimal(object):
...
@@ -1816,7 +1826,7 @@ class Decimal(object):
if
exp
.
_isinfinity
()
or
self
.
_isinfinity
():
if
exp
.
_isinfinity
()
or
self
.
_isinfinity
():
if
exp
.
_isinfinity
()
and
self
.
_isinfinity
():
if
exp
.
_isinfinity
()
and
self
.
_isinfinity
():
return
self
#
i
f both are inf, it is OK
return
self
#
I
f both are inf, it is OK
if
context
is
None
:
if
context
is
None
:
context
=
getcontext
()
context
=
getcontext
()
return
context
.
_raise_error
(
InvalidOperation
,
return
context
.
_raise_error
(
InvalidOperation
,
...
@@ -1848,7 +1858,8 @@ class Decimal(object):
...
@@ -1848,7 +1858,8 @@ class Decimal(object):
if
self
.
_is_special
:
if
self
.
_is_special
:
if
self
.
_isinfinity
():
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
)
ans
=
self
.
_check_nans
(
context
=
context
)
if
ans
:
if
ans
:
...
@@ -1920,13 +1931,13 @@ class Decimal(object):
...
@@ -1920,13 +1931,13 @@ class Decimal(object):
return
Decimal
(
self
)
return
Decimal
(
self
)
if
not
self
:
if
not
self
:
#exponent = self._exp / 2, using round_down.
#
exponent = self._exp / 2, using round_down.
#if self._exp < 0:
#
if self._exp < 0:
# exp = (self._exp+1) // 2
# exp = (self._exp+1) // 2
#else:
#
else:
exp
=
(
self
.
_exp
)
//
2
exp
=
(
self
.
_exp
)
//
2
if
self
.
_sign
==
1
:
if
self
.
_sign
==
1
:
#sqrt(-0) = -0
#
sqrt(-0) = -0
return
Decimal
(
(
1
,
(
0
,),
exp
))
return
Decimal
(
(
1
,
(
0
,),
exp
))
else
:
else
:
return
Decimal
(
(
0
,
(
0
,),
exp
))
return
Decimal
(
(
0
,
(
0
,),
exp
))
...
@@ -1960,8 +1971,7 @@ class Decimal(object):
...
@@ -1960,8 +1971,7 @@ class Decimal(object):
ans
=
ans
.
__add__
(
tmp
.
__mul__
(
Decimal
((
0
,
(
8
,
1
,
9
),
-
3
)),
ans
=
ans
.
__add__
(
tmp
.
__mul__
(
Decimal
((
0
,
(
8
,
1
,
9
),
-
3
)),
context
=
context
),
context
=
context
)
context
=
context
),
context
=
context
)
ans
.
_exp
-=
1
+
tmp
.
adjusted
()
//
2
ans
.
_exp
-=
1
+
tmp
.
adjusted
()
//
2
# ans is now a linear approximation.
#ans is now a linear approximation.
Emax
,
Emin
=
context
.
Emax
,
context
.
Emin
Emax
,
Emin
=
context
.
Emax
,
context
.
Emin
context
.
Emax
,
context
.
Emin
=
DefaultContext
.
Emax
,
DefaultContext
.
Emin
context
.
Emax
,
context
.
Emin
=
DefaultContext
.
Emax
,
DefaultContext
.
Emin
...
@@ -1977,12 +1987,12 @@ class Decimal(object):
...
@@ -1977,12 +1987,12 @@ class Decimal(object):
if
context
.
prec
==
maxp
:
if
context
.
prec
==
maxp
:
break
break
#
r
ound to the answer's precision-- the only error can be 1 ulp.
#
R
ound to the answer's precision-- the only error can be 1 ulp.
context
.
prec
=
firstprec
context
.
prec
=
firstprec
prevexp
=
ans
.
adjusted
()
prevexp
=
ans
.
adjusted
()
ans
=
ans
.
_round
(
context
=
context
)
ans
=
ans
.
_round
(
context
=
context
)
#Now, check if the other last digits are better.
#
Now, check if the other last digits are better.
context
.
prec
=
firstprec
+
1
context
.
prec
=
firstprec
+
1
# In case we rounded up another digit and we should actually go lower.
# In case we rounded up another digit and we should actually go lower.
if
prevexp
!=
ans
.
adjusted
():
if
prevexp
!=
ans
.
adjusted
():
...
@@ -2014,10 +2024,10 @@ class Decimal(object):
...
@@ -2014,10 +2024,10 @@ class Decimal(object):
context
.
_raise_error
(
Rounded
)
context
.
_raise_error
(
Rounded
)
context
.
_raise_error
(
Inexact
)
context
.
_raise_error
(
Inexact
)
else
:
else
:
#Exact answer, so let's set the exponent right.
#
Exact answer, so let's set the exponent right.
#if self._exp < 0:
#
if self._exp < 0:
# exp = (self._exp +1)// 2
# exp = (self._exp +1)// 2
#else:
#
else:
exp
=
self
.
_exp
//
2
exp
=
self
.
_exp
//
2
context
.
prec
+=
ans
.
_exp
-
exp
context
.
prec
+=
ans
.
_exp
-
exp
ans
=
ans
.
_rescale
(
exp
,
context
=
context
)
ans
=
ans
.
_rescale
(
exp
,
context
=
context
)
...
@@ -2052,13 +2062,13 @@ class Decimal(object):
...
@@ -2052,13 +2062,13 @@ class Decimal(object):
ans
=
self
ans
=
self
c
=
self
.
__cmp__
(
other
)
c
=
self
.
__cmp__
(
other
)
if
c
==
0
:
if
c
==
0
:
#
i
f both operands are finite and equal in numerical value
#
I
f both operands are finite and equal in numerical value
# then an ordering is applied:
# then an ordering is applied:
#
#
#
i
f the signs differ then max returns the operand with the
#
I
f the signs differ then max returns the operand with the
# positive sign and min returns the operand with the negative sign
# positive sign and min returns the operand with the negative sign
#
#
#
i
f the signs are the same then the exponent is used to select
#
I
f the signs are the same then the exponent is used to select
# the result.
# the result.
if
self
.
_sign
!=
other
.
_sign
:
if
self
.
_sign
!=
other
.
_sign
:
if
self
.
_sign
:
if
self
.
_sign
:
...
@@ -2079,7 +2089,7 @@ class Decimal(object):
...
@@ -2079,7 +2089,7 @@ class Decimal(object):
def
min
(
self
,
other
,
context
=
None
):
def
min
(
self
,
other
,
context
=
None
):
"""Returns the smaller value.
"""Returns the smaller value.
l
ike min(self, other) except if one is not a number, returns
L
ike min(self, other) except if one is not a number, returns
NaN (and signals if one is sNaN). Also rounds.
NaN (and signals if one is sNaN). Also rounds.
"""
"""
other
=
_convert_other
(
other
)
other
=
_convert_other
(
other
)
...
@@ -2087,7 +2097,7 @@ class Decimal(object):
...
@@ -2087,7 +2097,7 @@ class Decimal(object):
return
other
return
other
if
self
.
_is_special
or
other
.
_is_special
:
if
self
.
_is_special
or
other
.
_is_special
:
#
i
f one operand is a quiet NaN and the other is number, then the
#
I
f one operand is a quiet NaN and the other is number, then the
# number is always returned
# number is always returned
sn
=
self
.
_isnan
()
sn
=
self
.
_isnan
()
on
=
other
.
_isnan
()
on
=
other
.
_isnan
()
...
@@ -2101,13 +2111,13 @@ class Decimal(object):
...
@@ -2101,13 +2111,13 @@ class Decimal(object):
ans
=
self
ans
=
self
c
=
self
.
__cmp__
(
other
)
c
=
self
.
__cmp__
(
other
)
if
c
==
0
:
if
c
==
0
:
#
i
f both operands are finite and equal in numerical value
#
I
f both operands are finite and equal in numerical value
# then an ordering is applied:
# then an ordering is applied:
#
#
#
i
f the signs differ then max returns the operand with the
#
I
f the signs differ then max returns the operand with the
# positive sign and min returns the operand with the negative sign
# positive sign and min returns the operand with the negative sign
#
#
#
i
f the signs are the same then the exponent is used to select
#
I
f the signs are the same then the exponent is used to select
# the result.
# the result.
if
self
.
_sign
!=
other
.
_sign
:
if
self
.
_sign
!=
other
.
_sign
:
if
other
.
_sign
:
if
other
.
_sign
:
...
@@ -2142,11 +2152,11 @@ class Decimal(object):
...
@@ -2142,11 +2152,11 @@ class Decimal(object):
"""Return the adjusted exponent of self"""
"""Return the adjusted exponent of self"""
try
:
try
:
return
self
.
_exp
+
len
(
self
.
_int
)
-
1
return
self
.
_exp
+
len
(
self
.
_int
)
-
1
#If NaN or Infinity, self._exp is string
#
If NaN or Infinity, self._exp is string
except
TypeError
:
except
TypeError
:
return
0
return
0
#
s
upport for pickling, copy, and deepcopy
#
S
upport for pickling, copy, and deepcopy
def
__reduce__
(
self
):
def
__reduce__
(
self
):
return
(
self
.
__class__
,
(
str
(
self
),))
return
(
self
.
__class__
,
(
str
(
self
),))
...
@@ -2160,19 +2170,20 @@ class Decimal(object):
...
@@ -2160,19 +2170,20 @@ class Decimal(object):
return
self
# My components are also immutable
return
self
# My components are also immutable
return
self
.
__class__
(
str
(
self
))
return
self
.
__class__
(
str
(
self
))
##### Context class ###########################################
##### Context class ###########################################
###############
# Get rounding method function:
# get rounding method function:
rounding_functions
=
[
name
for
name
in
Decimal
.
__dict__
.
keys
()
rounding_functions
=
[
name
for
name
in
Decimal
.
__dict__
.
keys
()
if
name
.
startswith
(
'_round_'
)]
if
name
.
startswith
(
'_round_'
)]
for
name
in
rounding_functions
:
for
name
in
rounding_functions
:
#
n
ame is like _round_half_even, goes to the global ROUND_HALF_EVEN value.
#
N
ame is like _round_half_even, goes to the global ROUND_HALF_EVEN value.
globalname
=
name
[
1
:]
.
upper
()
globalname
=
name
[
1
:]
.
upper
()
val
=
globals
()[
globalname
]
val
=
globals
()[
globalname
]
Decimal
.
_pick_rounding_function
[
val
]
=
name
Decimal
.
_pick_rounding_function
[
val
]
=
name
del
name
,
val
,
globalname
,
rounding_functions
del
name
,
val
,
globalname
,
rounding_functions
class
ContextManager
(
object
):
class
ContextManager
(
object
):
"""Helper class to simplify Context management.
"""Helper class to simplify Context management.
...
@@ -2197,12 +2208,13 @@ class ContextManager(object):
...
@@ -2197,12 +2208,13 @@ class ContextManager(object):
def
__exit__
(
self
,
t
,
v
,
tb
):
def
__exit__
(
self
,
t
,
v
,
tb
):
setcontext
(
self
.
saved_context
)
setcontext
(
self
.
saved_context
)
class
Context
(
object
):
class
Context
(
object
):
"""Contains the context for a Decimal instance.
"""Contains the context for a Decimal instance.
Contains:
Contains:
prec - precision (for use in rounding, division, square roots..)
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?
_rounding_decision - ALWAYS_ROUND, NEVER_ROUND -- do you round?
traps - If traps[exception] = 1, then the exception is
traps - If traps[exception] = 1, then the exception is
raised when it is caused. Otherwise, a value is
raised when it is caused. Otherwise, a value is
...
@@ -2243,9 +2255,13 @@ class Context(object):
...
@@ -2243,9 +2255,13 @@ class Context(object):
def
__repr__
(
self
):
def
__repr__
(
self
):
"""Show the current context."""
"""Show the current context."""
s
=
[]
s
=
[]
s
.
append
(
'Context(prec=
%(prec)
d, rounding=
%(rounding)
s, Emin=
%(Emin)
d, Emax=
%(Emax)
d, capitals=
%(capitals)
d'
%
vars
(
self
))
s
.
append
(
s
.
append
(
'flags=['
+
', '
.
join
([
f
.
__name__
for
f
,
v
in
self
.
flags
.
items
()
if
v
])
+
']'
)
'Context(prec=
%(prec)
d, rounding=
%(rounding)
s, Emin=
%(Emin)
d, Emax=
%(Emax)
d, capitals=
%(capitals)
d'
s
.
append
(
'traps=['
+
', '
.
join
([
t
.
__name__
for
t
,
v
in
self
.
traps
.
items
()
if
v
])
+
']'
)
%
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
)
+
')'
return
', '
.
join
(
s
)
+
')'
def
get_manager
(
self
):
def
get_manager
(
self
):
...
@@ -2265,9 +2281,10 @@ class Context(object):
...
@@ -2265,9 +2281,10 @@ class Context(object):
def
copy
(
self
):
def
copy
(
self
):
"""Returns a deep copy from self."""
"""Returns a deep copy from self."""
nc
=
Context
(
self
.
prec
,
self
.
rounding
,
self
.
traps
.
copy
(),
self
.
flags
.
copy
(),
nc
=
Context
(
self
.
prec
,
self
.
rounding
,
self
.
traps
.
copy
(),
self
.
_rounding_decision
,
self
.
Emin
,
self
.
Emax
,
self
.
flags
.
copy
(),
self
.
_rounding_decision
,
self
.
capitals
,
self
.
_clamp
,
self
.
_ignored_flags
)
self
.
Emin
,
self
.
Emax
,
self
.
capitals
,
self
.
_clamp
,
self
.
_ignored_flags
)
return
nc
return
nc
__copy__
=
copy
__copy__
=
copy
...
@@ -2281,16 +2298,16 @@ class Context(object):
...
@@ -2281,16 +2298,16 @@ class Context(object):
"""
"""
error
=
_condition_map
.
get
(
condition
,
condition
)
error
=
_condition_map
.
get
(
condition
,
condition
)
if
error
in
self
.
_ignored_flags
:
if
error
in
self
.
_ignored_flags
:
#Don't touch the flag
#
Don't touch the flag
return
error
()
.
handle
(
self
,
*
args
)
return
error
()
.
handle
(
self
,
*
args
)
self
.
flags
[
error
]
+=
1
self
.
flags
[
error
]
+=
1
if
not
self
.
traps
[
error
]:
if
not
self
.
traps
[
error
]:
#The errors define how to handle themselves.
#
The errors define how to handle themselves.
return
condition
()
.
handle
(
self
,
*
args
)
return
condition
()
.
handle
(
self
,
*
args
)
# Errors should only be risked on copies of the context
# Errors should only be risked on copies of the context
#self._ignored_flags = []
#
self._ignored_flags = []
raise
error
,
explanation
raise
error
,
explanation
def
_ignore_all_flags
(
self
):
def
_ignore_all_flags
(
self
):
...
@@ -2314,7 +2331,7 @@ class Context(object):
...
@@ -2314,7 +2331,7 @@ class Context(object):
def
__hash__
(
self
):
def
__hash__
(
self
):
"""A Context cannot be hashed."""
"""A Context cannot be hashed."""
# We inherit object.__hash__, so we must deny this explicitly
# 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
):
def
Etiny
(
self
):
"""Returns Etiny (= Emin - prec + 1)"""
"""Returns Etiny (= Emin - prec + 1)"""
...
@@ -2340,7 +2357,6 @@ class Context(object):
...
@@ -2340,7 +2357,6 @@ class Context(object):
This will make it not round for that operation.
This will make it not round for that operation.
"""
"""
rounding
=
self
.
_rounding_decision
rounding
=
self
.
_rounding_decision
self
.
_rounding_decision
=
type
self
.
_rounding_decision
=
type
return
rounding
return
rounding
...
@@ -2369,7 +2385,7 @@ class Context(object):
...
@@ -2369,7 +2385,7 @@ class Context(object):
d
=
Decimal
(
num
,
context
=
self
)
d
=
Decimal
(
num
,
context
=
self
)
return
d
.
_fix
(
self
)
return
d
.
_fix
(
self
)
#Methods
#
Methods
def
abs
(
self
,
a
):
def
abs
(
self
,
a
):
"""Returns the absolute value of the operand.
"""Returns the absolute value of the operand.
...
@@ -2528,10 +2544,10 @@ class Context(object):
...
@@ -2528,10 +2544,10 @@ class Context(object):
def
multiply
(
self
,
a
,
b
):
def
multiply
(
self
,
a
,
b
):
"""multiply multiplies two operands.
"""multiply multiplies two operands.
If either operand is a special value then the general rules
apply.
If either operand is a special value then the general rules
Otherwise, the operands are multiplied together ('long multiplication'),
apply. Otherwise, the operands are multiplied together
resulting in a number which may be as long as the sum of the lengths
('long multiplication'), resulting in a number which may be
of the two operands.
as long as the sum of the lengths
of the two operands.
>>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3'))
>>> ExtendedContext.multiply(Decimal('1.20'), Decimal('3'))
Decimal("3.60")
Decimal("3.60")
...
@@ -2592,8 +2608,8 @@ class Context(object):
...
@@ -2592,8 +2608,8 @@ class Context(object):
1) before use.
1) before use.
If the increased precision needed for the intermediate calculations
If the increased precision needed for the intermediate calculations
exceeds the capabilities of the implementation then an Invalid
operation
exceeds the capabilities of the implementation then an Invalid
condition is raised.
operation
condition is raised.
If, when raising to a negative power, an underflow occurs during the
If, when raising to a negative power, an underflow occurs during the
division into 1, the operation is not halted at that point but
division into 1, the operation is not halted at that point but
...
@@ -2631,7 +2647,7 @@ class Context(object):
...
@@ -2631,7 +2647,7 @@ class Context(object):
return
a
.
__pow__
(
b
,
modulo
,
context
=
self
)
return
a
.
__pow__
(
b
,
modulo
,
context
=
self
)
def
quantize
(
self
,
a
,
b
):
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
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
operand. It may be rounded using the current rounding setting (if the
...
@@ -2641,8 +2657,8 @@ class Context(object):
...
@@ -2641,8 +2657,8 @@ class Context(object):
Unlike other operations, if the length of the coefficient after the
Unlike other operations, if the length of the coefficient after the
quantize operation would be greater than precision then an Invalid
quantize operation would be greater than precision then an Invalid
operation condition is raised.
This guarantees that, unless there is an
operation condition is raised.
This guarantees that, unless there is
error condition, the exponent of the result of a quantize is always
an
error condition, the exponent of the result of a quantize is always
equal to that of the right-hand operand.
equal to that of the right-hand operand.
Also unlike other operations, quantize will never raise Underflow, even
Also unlike other operations, quantize will never raise Underflow, even
...
@@ -2685,9 +2701,9 @@ class Context(object):
...
@@ -2685,9 +2701,9 @@ class Context(object):
"""Returns the remainder from integer division.
"""Returns the remainder from integer division.
The result is the residue of the dividend after the operation of
The result is the residue of the dividend after the operation of
calculating integer division as described for divide-integer, rounded
to
calculating integer division as described for divide-integer, rounded
precision digits if necessary. The sign of the result, if non-zero, is
to precision digits if necessary. The sign of the result, if non-zero,
the same as that of the original dividend.
is
the same as that of the original dividend.
This operation will fail under the same conditions as integer division
This operation will fail under the same conditions as integer division
(that is, if integer division on the same two operands would fail, the
(that is, if integer division on the same two operands would fail, the
...
@@ -2753,7 +2769,7 @@ class Context(object):
...
@@ -2753,7 +2769,7 @@ class Context(object):
return
a
.
same_quantum
(
b
)
return
a
.
same_quantum
(
b
)
def
sqrt
(
self
,
a
):
def
sqrt
(
self
,
a
):
"""
Returns the s
quare root of a non-negative number to context precision.
"""
S
quare root of a non-negative number to context precision.
If the result must be inexact, it is rounded using the round-half-even
If the result must be inexact, it is rounded using the round-half-even
algorithm.
algorithm.
...
@@ -2835,6 +2851,7 @@ class Context(object):
...
@@ -2835,6 +2851,7 @@ class Context(object):
"""
"""
return
a
.
to_integral
(
context
=
self
)
return
a
.
to_integral
(
context
=
self
)
class
_WorkRep
(
object
):
class
_WorkRep
(
object
):
__slots__
=
(
'sign'
,
'int'
,
'exp'
)
__slots__
=
(
'sign'
,
'int'
,
'exp'
)
# sign: 0 or 1
# sign: 0 or 1
...
@@ -2889,9 +2906,9 @@ def _normalize(op1, op2, shouldround = 0, prec = 0):
...
@@ -2889,9 +2906,9 @@ def _normalize(op1, op2, shouldround = 0, prec = 0):
other_len
=
len
(
str
(
other
.
int
))
other_len
=
len
(
str
(
other
.
int
))
if
numdigits
>
(
other_len
+
prec
+
1
-
tmp_len
):
if
numdigits
>
(
other_len
+
prec
+
1
-
tmp_len
):
# If the difference in adjusted exps is > prec+1, we know
# If the difference in adjusted exps is > prec+1, we know
# other is insignificant, so might as well put a 1 after the
precision.
# other is insignificant, so might as well put a 1 after the
#
(since this is only for addition.) Also stops use of massive longs.
#
precision (since this is only for addition). Also stops
# use of massive longs.
extend
=
prec
+
2
-
tmp_len
extend
=
prec
+
2
-
tmp_len
if
extend
<=
0
:
if
extend
<=
0
:
extend
=
1
extend
=
1
...
@@ -2913,13 +2930,13 @@ def _adjust_coefficients(op1, op2):
...
@@ -2913,13 +2930,13 @@ def _adjust_coefficients(op1, op2):
Used on _WorkRep instances during division.
Used on _WorkRep instances during division.
"""
"""
adjust
=
0
adjust
=
0
#If op1 is smaller, make it larger
#
If op1 is smaller, make it larger
while
op2
.
int
>
op1
.
int
:
while
op2
.
int
>
op1
.
int
:
op1
.
int
*=
10
op1
.
int
*=
10
op1
.
exp
-=
1
op1
.
exp
-=
1
adjust
+=
1
adjust
+=
1
#If op2 is too small, make it larger
#
If op2 is too small, make it larger
while
op1
.
int
>=
(
10
*
op2
.
int
):
while
op1
.
int
>=
(
10
*
op2
.
int
):
op2
.
int
*=
10
op2
.
int
*=
10
op2
.
exp
-=
1
op2
.
exp
-=
1
...
@@ -2927,7 +2944,8 @@ def _adjust_coefficients(op1, op2):
...
@@ -2927,7 +2944,8 @@ def _adjust_coefficients(op1, op2):
return
op1
,
op2
,
adjust
return
op1
,
op2
,
adjust
##### Helper Functions ########################################
##### Helper Functions #######################################################
def
_convert_other
(
other
):
def
_convert_other
(
other
):
"""Convert other to Decimal.
"""Convert other to Decimal.
...
@@ -2968,16 +2986,16 @@ def _isnan(num):
...
@@ -2968,16 +2986,16 @@ def _isnan(num):
if
not
num
:
if
not
num
:
return
0
return
0
#get the sign, get rid of trailing [+-]
#
get the sign, get rid of trailing [+-]
sign
=
0
sign
=
0
if
num
[
0
]
==
'+'
:
if
num
[
0
]
==
'+'
:
num
=
num
[
1
:]
num
=
num
[
1
:]
elif
num
[
0
]
==
'-'
:
#elif avoids '+-nan'
elif
num
[
0
]
==
'-'
:
#
elif avoids '+-nan'
num
=
num
[
1
:]
num
=
num
[
1
:]
sign
=
1
sign
=
1
if
num
.
startswith
(
'nan'
):
if
num
.
startswith
(
'nan'
):
if
len
(
num
)
>
3
and
not
num
[
3
:]
.
isdigit
():
#
diagnostic info
if
len
(
num
)
>
3
and
not
num
[
3
:]
.
isdigit
():
#
diagnostic info
return
0
return
0
return
(
1
,
sign
,
num
[
3
:]
.
lstrip
(
'0'
))
return
(
1
,
sign
,
num
[
3
:]
.
lstrip
(
'0'
))
if
num
.
startswith
(
'snan'
):
if
num
.
startswith
(
'snan'
):
...
@@ -2987,7 +3005,7 @@ def _isnan(num):
...
@@ -2987,7 +3005,7 @@ def _isnan(num):
return
0
return
0
##### Setup Specific Contexts ################################
##### Setup Specific Contexts ################################
################
# The default context prototype used by Context()
# The default context prototype used by Context()
# Is mutable, so that new contexts can have different default values
# Is mutable, so that new contexts can have different default values
...
@@ -3020,19 +3038,19 @@ ExtendedContext = Context(
...
@@ -3020,19 +3038,19 @@ ExtendedContext = Context(
)
)
##### Useful Constants (internal use only) ####################
##### Useful Constants (internal use only) ####################
###############
#Reusable defaults
#
Reusable defaults
Inf
=
Decimal
(
'Inf'
)
Inf
=
Decimal
(
'Inf'
)
negInf
=
Decimal
(
'-Inf'
)
negInf
=
Decimal
(
'-Inf'
)
#Infsign[sign] is infinity w/ that sign
#
Infsign[sign] is infinity w/ that sign
Infsign
=
(
Inf
,
negInf
)
Infsign
=
(
Inf
,
negInf
)
NaN
=
Decimal
(
'NaN'
)
NaN
=
Decimal
(
'NaN'
)
##### crud for parsing strings #################################
##### crud for parsing strings #################################
###############
import
re
import
re
# There's an optional sign at the start, and an optional exponent
# There's an optional sign at the start, and an optional exponent
...
@@ -3052,13 +3070,16 @@ _parser = re.compile(r"""
...
@@ -3052,13 +3070,16 @@ _parser = re.compile(r"""
([eE](?P<exp>[-+]? \d+))?
([eE](?P<exp>[-+]? \d+))?
# \s*
# \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
del
re
# return sign, n, p s.t. float string value == -1**sign * n * 10**p exactly
def
_string2exact
(
s
):
def
_string2exact
(
s
):
"""Return sign, n, p s.t.
Float string value == -1**sign * n * 10**p exactly
"""
m
=
_parser
(
s
)
m
=
_parser
(
s
)
if
m
is
None
:
if
m
is
None
:
raise
ValueError
(
"invalid literal for Decimal:
%
r"
%
s
)
raise
ValueError
(
"invalid literal for Decimal:
%
r"
%
s
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment