The cdecimal module is compatible with decimal.py. Since the official documentation is valid, the rest of this document focuses on the few remaining differences as well as extra features.
prec, Emin, Emax, rounding, capitals and clamp are implemented as getters/setters.
An additional field _allcr toggles correct rounding for exp, ln and log10. If enabled (default), all methods except power and invroot are correctly rounded.
traps and flags have the custom type SignalDict, which behaves like a dictionary for most purposes. This is the familiar interface from decimal.py.
Internally, traps and flags are just C unsigned integers. cdecimal provides the option to access the integers directly using the getters/setters _traps and _flags.
The use of the two interfaces can be mixed freely. The following table shows how the SignalDict items and the C-flags are related:
SignalDict |
C signals |
C conditions |
---|---|---|
InvalidOperation |
DecIEEEInvalidOperation |
DecConversionSyntax |
DecDivisionImpossible |
||
DecDivisionUndefined |
||
DecInvalidContext |
||
DecInvalidOperation |
||
DecMallocError |
||
Clamped |
DecClamped |
DecClamped |
DivisionByZero |
DecDivisionByZero |
DecDivisionByZero |
FloatOperation [1] |
DecFloatOperation |
DecFloatOperation |
Inexact |
DecInexact |
DecInexact |
Rounded |
DecRounded |
DecRounded |
Subnormal |
DecSubnormal |
DecSubnormal |
Overflow |
DecOverflow |
DecOverflow |
Underflow |
DecUnderflow |
DecUnderflow |
[1] | cdecimal extension. |
An example of mixing the two interfaces:
>>> from cdecimal import *
>>> c = getcontext() # Global (thread-local) context
>>>
>>> c.traps[Inexact] = True # Trap the Inexact signal
>>> c.traps[Inexact] = False # Clear the Inexact signal
>>>
>>> c._traps |= DecInexact # Trap the Inexact signal
>>> c.traps[Inexact]
True
>>> c._traps &= ~DecInexact # Clear the Inexact signal
>>> c.traps[Inexact]
False
Module constants:
cdecimal 32-bit cdecimal 64-bit MAX_PREC 425000000 999999999999999999 MAX_EMAX 425000000 999999999999999999 MIN_EMIN -425000000 -999999999999999999
Valid ranges:
decimal.py cdecimal prec [1, unlimited] [1, MPD_MAX_PREC] Emax [0, unlimited] [0, MPD_MAX_EMAX] Emin [-unlimited, 0] [MPD_MIN_EMIN, 0]
The choice whether the default context is thread local or global is made at compile time. If thread local contexts are enabled, the module constant HAVE_THREADS has a value of 1. Otherwise, the value is 0.
By default, local contexts are enabled.
The Decimal constructor does not observe the current context, i.e. any value is read exactly as entered. Since the context of cdecimal has limits, the following approach is used:
If an Inexact or Rounded condition occurs during conversion, InvalidOperation is raised and the result is NaN. In this case, the create_decimal context method has to be used.
The power method in decimal.py is correctly rounded. cdecimal currently only guarantees an error less than 1ULP+t, where t has a maximum of 0.1ULP, but is almost always less than 0.01ULP.
In Python 2.7 and 3.2 the rules for mixing decimals and floats were relaxed. This can give rise to mistakes:
>>> Decimal(1.1) # meaning Decimal("1.1")
Decimal('1.100000000000000088817841970012523233890533447265625')
>>> x = Decimal("1.9")
>>> x > 1.9 # meaning Decimal(1.9)
True
In order to prevent accidental mixing, cdecimal has an additional FloatOperation signal. Here is the behavior with the trap set:
>>> c = getcontext()
>>> c.traps[FloatOperation] = True
>>> Decimal(1.9)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
cdecimal.FloatOperation: [<class 'cdecimal.FloatOperation'>]
>>>
>>> x = Decimal("1.9")
>>> x > 1.9
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
cdecimal.FloatOperation: [<class 'cdecimal.FloatOperation'>]
>>>
For compatibility with decimal.py the FloatOperation signal is off by default. This is the standard behavior for mixed operations across several Python versions:
The same table with the FloatOperation signal enabled:
2.5 2.6 2.7 3.1 3.2 mixed arithmetic TypeError TypeError TypeError TypeError TypeError constructor TypeError TypeError FloatOp TypeError FloatOp __eq__ false false exact false exact __ne__ true true exact true exact ordering FloatOp [5] FloatOp FloatOp FloatOp FloatOp
[2] always false
[3] always true
[4] exact conversions or comparisons
[5] raises FloatOperation
Return a context object initialized to the proper values for one of the IEEE interchange formats. The argument must be a multiple of 32 and less than IEEE_CONTEXT_MAX_BITS.
For the most common values, the following constants are provided:
DECIMAL32 | DECIMAL64 | DECIMAL128 | |
---|---|---|---|
prec | 7 | 16 | 34 |
emax | 96 | 384 | 6144 |
emin | -95 | -383 | -6143 |
round | ROUND_HALF_EVEN | ROUND_HALF_EVEN | ROUND_HALF_EVEN |
traps | 0 | 0 | 0 |
status | 0 | 0 | 0 |
newtrap | 0 | 0 | 0 |
clamp | 1 | 1 | 1 |
allcr | 1 | 1 | 1 |