FAILURE MAP
← Case archive

FA-16916 / Floating-point arithmetic / Open access

Decimal quantization mistakes an exact subnormal for underflow · case 01

Decimal quantization mistakes an exact subnormal for underflow.

Verified by executionVariant 1 · 11 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

Decimal quantization mistakes an exact subnormal for underflow. The faulty expression is flags=sorted("Underflow" if signal is decimal.Subnormal else signal.__name__ for signal,raised in ctx.flags.items() if raised).

VERIFIED REPAIR

Apply the contract at this fault site using flags=sorted(signal.__name__ for signal,raised in ctx.flags.items() if raised).

Unsuccessful approach: The attempted local correction flags=sorted(signal.__name__ for signal,raised in ctx.flags.items() if raised and signal is not decimal.Subnormal) still violates the explicit regression fixtures.

Case contract

Quantize a decimal text to 10**exponent using a fresh precision-limited decimal context, half-even rounding, Emin=-9 and Emax=9. All traps are disabled; return result string and raised flag names. The coefficient precision includes trailing zeros imposed by the target quantum.

Why this case matters

An offline floating representation model isolates a reproducible arithmetic fault.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
import decimal
from decimal import Decimal, Context, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_DOWN

N = 1
observations = []
def solve(text, exponent, precision):
    ctx=Context(prec=precision,rounding=ROUND_HALF_EVEN,Emin=-9,Emax=9)
    for signal in ctx.traps: ctx.traps[signal]=False
    ctx.clear_flags()
    value=Decimal(text)
    quantum=Decimal((0,(1,),exponent))
    result=ctx.quantize(value,quantum)
    flags=sorted("Underflow" if signal is decimal.Subnormal else signal.__name__ for signal,raised in ctx.flags.items() if raised)
    return [str(result),flags]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('tie odd', solve(str(N)+".255",-2,6), [str(N)+".26",["Inexact","Rounded"]])
check('tie even', solve(str(N)+".245",-2,6), [str(N)+".24",["Inexact","Rounded"]])
check('rounded exact', solve(str(N)+".200",-2,6), [str(N)+".20",["Rounded"]])
check('already exact', solve(str(N)+".20",-2,6), [str(N)+".20",[]])
check('one excess digit', solve("123.45",-2,4), ["NaN",["InvalidOperation"]])
check('coefficient too large', solve("12345.67",-2,4), ["NaN",["InvalidOperation"]])
check('subnormal exact', solve("1e-10",-10,6), ["1E-10",["Subnormal"]])
check('negative zero', solve("-0.004",-2,6), ["-0.00",["Inexact","Rounded"]])
check('positive zero', solve("0.004",-2,6), ["0.00",["Inexact","Rounded"]])
check('integer quantum', solve("123.4",1,6), ["1.2E+2",["Inexact","Rounded"]])
check('overflow exponent', solve("1e10",0,6), ["NaN",["InvalidOperation"]])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
tie odd['1.26', ['Inexact', 'Rounded']]['1.26', ['Inexact', 'Rounded']]Passed
tie even['1.24', ['Inexact', 'Rounded']]['1.24', ['Inexact', 'Rounded']]Passed
rounded exact['1.20', ['Rounded']]['1.20', ['Rounded']]Passed
already exact['1.20', []]['1.20', []]Passed
one excess digit['NaN', ['InvalidOperation']]['NaN', ['InvalidOperation']]Passed
coefficient too large['NaN', ['InvalidOperation']]['NaN', ['InvalidOperation']]Passed
subnormal exact['1E-10', ['Underflow']]['1E-10', ['Subnormal']]Failed
negative zero['-0.00', ['Inexact', 'Rounded']]['-0.00', ['Inexact', 'Rounded']]Passed
positive zero['0.00', ['Inexact', 'Rounded']]['0.00', ['Inexact', 'Rounded']]Passed
integer quantum['1.2E+2', ['Inexact', 'Rounded']]['1.2E+2', ['Inexact', 'Rounded']]Passed
overflow exponent['NaN', ['InvalidOperation']]['NaN', ['InvalidOperation']]Passed

SHA-256 / c2002b8b5a69be0af2c4190a039e28e5866c3cc85d3f30541f976f3eca191d5a

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
import decimal
from decimal import Decimal, Context, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_DOWN

N = 1
observations = []
def solve(text, exponent, precision):
    ctx=Context(prec=precision,rounding=ROUND_HALF_EVEN,Emin=-9,Emax=9)
    for signal in ctx.traps: ctx.traps[signal]=False
    ctx.clear_flags()
    value=Decimal(text)
    quantum=Decimal((0,(1,),exponent))
    result=ctx.quantize(value,quantum)
    flags=sorted(signal.__name__ for signal,raised in ctx.flags.items() if raised and signal is not decimal.Subnormal)
    return [str(result),flags]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('tie odd', solve(str(N)+".255",-2,6), [str(N)+".26",["Inexact","Rounded"]])
check('tie even', solve(str(N)+".245",-2,6), [str(N)+".24",["Inexact","Rounded"]])
check('rounded exact', solve(str(N)+".200",-2,6), [str(N)+".20",["Rounded"]])
check('already exact', solve(str(N)+".20",-2,6), [str(N)+".20",[]])
check('one excess digit', solve("123.45",-2,4), ["NaN",["InvalidOperation"]])
check('coefficient too large', solve("12345.67",-2,4), ["NaN",["InvalidOperation"]])
check('subnormal exact', solve("1e-10",-10,6), ["1E-10",["Subnormal"]])
check('negative zero', solve("-0.004",-2,6), ["-0.00",["Inexact","Rounded"]])
check('positive zero', solve("0.004",-2,6), ["0.00",["Inexact","Rounded"]])
check('integer quantum', solve("123.4",1,6), ["1.2E+2",["Inexact","Rounded"]])
check('overflow exponent', solve("1e10",0,6), ["NaN",["InvalidOperation"]])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
tie odd['1.26', ['Inexact', 'Rounded']]['1.26', ['Inexact', 'Rounded']]Passed
tie even['1.24', ['Inexact', 'Rounded']]['1.24', ['Inexact', 'Rounded']]Passed
rounded exact['1.20', ['Rounded']]['1.20', ['Rounded']]Passed
already exact['1.20', []]['1.20', []]Passed
one excess digit['NaN', ['InvalidOperation']]['NaN', ['InvalidOperation']]Passed
coefficient too large['NaN', ['InvalidOperation']]['NaN', ['InvalidOperation']]Passed
subnormal exact['1E-10', []]['1E-10', ['Subnormal']]Failed
negative zero['-0.00', ['Inexact', 'Rounded']]['-0.00', ['Inexact', 'Rounded']]Passed
positive zero['0.00', ['Inexact', 'Rounded']]['0.00', ['Inexact', 'Rounded']]Passed
integer quantum['1.2E+2', ['Inexact', 'Rounded']]['1.2E+2', ['Inexact', 'Rounded']]Passed
overflow exponent['NaN', ['InvalidOperation']]['NaN', ['InvalidOperation']]Passed

SHA-256 / 98776c898ce7ca5c6a66818c4dcedca1dc1e88ae3ee425f794387a04f36060e4

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
import decimal
from decimal import Decimal, Context, ROUND_HALF_EVEN, ROUND_HALF_UP, ROUND_DOWN

N = 1
observations = []
def solve(text, exponent, precision):
    ctx=Context(prec=precision,rounding=ROUND_HALF_EVEN,Emin=-9,Emax=9)
    for signal in ctx.traps: ctx.traps[signal]=False
    ctx.clear_flags()
    value=Decimal(text)
    quantum=Decimal((0,(1,),exponent))
    result=ctx.quantize(value,quantum)
    flags=sorted(signal.__name__ for signal,raised in ctx.flags.items() if raised)
    return [str(result),flags]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('tie odd', solve(str(N)+".255",-2,6), [str(N)+".26",["Inexact","Rounded"]])
check('tie even', solve(str(N)+".245",-2,6), [str(N)+".24",["Inexact","Rounded"]])
check('rounded exact', solve(str(N)+".200",-2,6), [str(N)+".20",["Rounded"]])
check('already exact', solve(str(N)+".20",-2,6), [str(N)+".20",[]])
check('one excess digit', solve("123.45",-2,4), ["NaN",["InvalidOperation"]])
check('coefficient too large', solve("12345.67",-2,4), ["NaN",["InvalidOperation"]])
check('subnormal exact', solve("1e-10",-10,6), ["1E-10",["Subnormal"]])
check('negative zero', solve("-0.004",-2,6), ["-0.00",["Inexact","Rounded"]])
check('positive zero', solve("0.004",-2,6), ["0.00",["Inexact","Rounded"]])
check('integer quantum', solve("123.4",1,6), ["1.2E+2",["Inexact","Rounded"]])
check('overflow exponent', solve("1e10",0,6), ["NaN",["InvalidOperation"]])
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
Boundary fixtureActualExpectedOutcome
tie odd['1.26', ['Inexact', 'Rounded']]['1.26', ['Inexact', 'Rounded']]Passed
tie even['1.24', ['Inexact', 'Rounded']]['1.24', ['Inexact', 'Rounded']]Passed
rounded exact['1.20', ['Rounded']]['1.20', ['Rounded']]Passed
already exact['1.20', []]['1.20', []]Passed
one excess digit['NaN', ['InvalidOperation']]['NaN', ['InvalidOperation']]Passed
coefficient too large['NaN', ['InvalidOperation']]['NaN', ['InvalidOperation']]Passed
subnormal exact['1E-10', ['Subnormal']]['1E-10', ['Subnormal']]Passed
negative zero['-0.00', ['Inexact', 'Rounded']]['-0.00', ['Inexact', 'Rounded']]Passed
positive zero['0.00', ['Inexact', 'Rounded']]['0.00', ['Inexact', 'Rounded']]Passed
integer quantum['1.2E+2', ['Inexact', 'Rounded']]['1.2E+2', ['Inexact', 'Rounded']]Passed
overflow exponent['NaN', ['InvalidOperation']]['NaN', ['InvalidOperation']]Passed

SHA-256 / 460468a042fcf6d67d4cb763ba48f3f98f817466899bf87246a676393d0e8269

Verification & scope

Controlled binary64 or explicitly stipulated miniature format; no hardware exception flags or platform floating environment are modeled. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.

Observations recorded using Python 3.12.14 at 2026-09-29T14:39:41.072927+00:00.

Case digest / 071fdb95ba71da840e6391daff92a1fc6ac73b2b2b97daf3f851d09f568bef11