Skip to content

_parse_numeric_exact misinterprets scientific notation (e.g., 1e6, 1e8) as hexadecimal, causing incorrect calculations #10

@rajanarahul93

Description

@rajanarahul93

Description

The helper function _parse_numeric_exact incorrectly parses scientific notation inputs like 1e6 and 1e8 as hexadecimal values instead of decimal/scientific notation.

This leads to silent incorrect results in both math_operation and compare_numbers.

Steps to Reproduce

from backend.calc_functions.calc_func import _parse_numeric_exact, math_operation, compare_numbers

_parse_numeric_exact("1e6")   # returns 486 (expected: 1000000)
_parse_numeric_exact("1e8")   # returns 488 (expected: 100000000)

math_operation(["1e8", "+", "1"])          # returns "489" (expected: "100000001")
compare_numbers(["1e8", ">", "1000000"])   # returns "false" (expected: "true")

Expected Behavior

  • "1e6" → 1000000

  • "1e8" → 100000000

  • Calculations and comparisons should use correct decimal values

Actual Behavior

  • "1e6" → 486 (interpreted as hex 0x1e6)

  • "1e8" → 488 (interpreted as hex 0x1e8)

  • Downstream calculations produce incorrect results without any error

Root Cause

In _parse_numeric_exact, the hex-detection logic runs before attempting to parse with Decimal.

if all(c in "0123456789abcdefABCDEF" for c in s) and any(c in "abcdefABCDEF" for c in s):
    return int(s, 16)

Strings like "1e6" satisfy this condition (e is treated as a hex character), so they are incorrectly parsed as hexadecimal.

Suggested Fix

Attempt decimal parsing before applying the ambiguous hex-detection logic:

if s.lower().startswith("0x"):
    return int(s, 16)

if re.fullmatch(r"[+-]?\d+", s):
    return int(s, 10)

try:
    return Decimal(s)
except InvalidOperation:
    pass

if all(c in "0123456789abcdefABCDEF" for c in s) and any(c in "abcdefABCDEF" for c in s):
    return int(s, 16)

Impact

  • Produces incorrect results silently

  • Affects core calculation features

  • Particularly problematic for values like "1e8" (commonly used for satoshis / BTC)

Additional Context

This format (1e6, 1e8) is already mentioned as supported in the function’s docstring, so current behavior contradicts documentation.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions