Skip to content

RealDigits of a rational: integer digits, the right period, zeros kept - #2036

Merged
rocky merged 4 commits into
Mathics3:masterfrom
tombouctou:audit-realdigits
Oct 18, 2026
Merged

rocky merged 4 commits into
Mathics3:masterfrom
tombouctou:audit-realdigits

Conversation

@tombouctou

Copy link
Copy Markdown
Collaborator

For a rational number with a repeating expansion RealDigits

  • returned the repeating digits as strings: RealDigits[1/7] was
    {{{"1", "4", "2", "8", "5", "7"}}, 0} (the output form hides the
    quotes, so the doctests and unit tests did not notice);
  • took everything after the decimal point as the period:
    RealDigits[1/6] gave {{{1, 6}}, 0} (0.161616...) instead of
    {{1, {6}}, 0}, RealDigits[1/14] gave {{{7, 1, 4, 2, 8, 5, 0}}, -1};
  • dropped the zeros of the integer part: RealDigits[703/7] (100.428...)
    gave {{1, {4, 2, 8, 5, 7, 1}}, 3};
  • raised ZeroDivisionError or TypeError for a base 1 or -2.

The digits now come from a long division that records where the
remainders start to repeat, with leading zeros moved into the exponent and
the shortest pre-period, as before (RealDigits[20/3] is {{{6}}, 1}). A
base below 2 gets RealDigits::rbase.

To reproduce on master:

RealDigits[1/7] // InputForm   (* {{{"1", "4", "2", "8", "5", "7"}}, 0} *)
RealDigits[1/6]                (* {{{1, 6}}, 0} *)
RealDigits[703/7]              (* {{1, {4, 2, 8, 5, 7, 1}}, 3} *)

Tests: new cases in test/builtin/atomic/test_numbers.py (test_realdigits_rational). They fail on current master and pass with this change.

The full pytest suite and the doctests pass with this change (run together with the other fixes from the same audit; the only pytest failures, in test_main.py and test_returncode.py, are the same as on master and come from the mathics script not being on PATH in our environment).

Found in a correctness audit of Mathics3 (differential checks against SymPy/mpmath/exact computation, and calls of every builtin with edge-case arguments).

🤖 Generated with Claude Code

tombouctou and others added 2 commits October 18, 2026 15:12
For a rational number with a repeating expansion RealDigits

  * returned the repeating digits as strings: RealDigits[1/7] was
    {{{"1", "4", "2", "8", "5", "7"}}, 0} (the output form hides the
    quotes, so the doctests and unit tests did not notice);
  * took everything after the decimal point as the period:
    RealDigits[1/6] gave {{{1, 6}}, 0} (0.161616...) instead of
    {{1, {6}}, 0}, RealDigits[1/14] gave {{{7, 1, 4, 2, 8, 5, 0}}, -1};
  * dropped the zeros of the integer part: RealDigits[703/7] (100.428...)
    gave {{1, {4, 2, 8, 5, 7, 1}}, 3};
  * raised ZeroDivisionError or TypeError for a base 1 or -2.

The digits now come from a long division that records where the
remainders start to repeat, with leading zeros moved into the exponent and
the shortest pre-period, as before (RealDigits[20/3] is {{{6}}, 1}). A
base below 2 gets RealDigits::rbase.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Comment thread mathics/eval/numbers/numbers.py Outdated
else:
break
return (head, tails)
def rational_digits(numerator: int, denominator: int, base: int):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to add a return signature here, e.g., tuple[int, int, int] or whatever.

(I have a hard time checking the exact type right now due to a local problem on my computer and the fact that this is not a branch in the repository.)

SymbolIntegerExponent = Symbol("IntegerExponent")


class Accuracy(Builtin):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When making changes to the class, you'd do me a favor and look for missing argument checking. Here we are missing expected_args = 1 as a class variable.

@rocky

rocky commented Oct 18, 2026

Copy link
Copy Markdown
Member

LGTM

@rocky
rocky merged commit 6daf405 into Mathics3:master Oct 18, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants