Python Forum

Full Version: shouldn't this raise an exception?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
shouldn't this raise some kind of exception, like a Decimal.UNDERFLOW or something like that, new?
lt2a/phil /home/phil 10> python3
Python 3.6.9 (default, Jan 26 2021, 15:33:00) 
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from decimal import *
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
>>> Decimal('1E999999')*Decimal('1E99')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.Overflow: [<class 'decimal.Overflow'>]
>>> Decimal('1E-999999')*Decimal('1E-99')
Decimal('0E-1000026')
>>> Decimal('1E-1000026')
Decimal('1E-1000026')
>>> 
it does not appear to be a representation issue, so i assume it is an operation issue.
>>> from decimal import *
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
>>> Decimal('1E-999999')*Decimal('1E-99')
Decimal('0E-1000026')
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[Clamped, Inexact, Rounded, Subnormal, Underflow], traps=[InvalidOperation, DivisionByZero, Overflow])
>>> 
Compare the differences in the output of getcontext() before and after operation that generates the underflow. flags now has a list of the special conditions. The Underflow flag was set. traps is a list of the flags, that when set, raise an exception. You can add Underflow to the traps if you want to raise an exception.

>>> setcontext(DefaultContext)
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
>>> getcontext().traps[Underflow] = True
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow, Underflow])
>>> Decimal('1E-999999')*Decimal('1E-99')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
decimal.Underflow: [<class 'decimal.Underflow'>]
>>>
from decimal import localcontext, Decimal


with localcontext() as ctx:
    ctx.Emin=-999999999999999999
    ctx.Emax=+999999999999999999

    print(Decimal('1E-999999')*Decimal('1E-99'))
i did not know about the traps. i guess there really are cases where you need to just continue after an underflow. having a way to suppress exceptions in a try/except would have been an alternate way. not all exceptions would be safe for that.

what raised my concern was the funny value that had a 0 mantissa. i remember ages ago having an HP-35 calculator where i found a way to get an invalid value like that and dividing a number by that would hard freeze the calculator (a divide by zero it failed to catch).