Skip to content

% returns 0 whenever an integer operand ends in 0: 37 % 10 == 0, 1234 % 100 == 0, 10 % 3 == 0 #135

Open

Description

@matt-edmondson

What's wrong

Mod (SignificantNumber/SignificantNumber.cs:269-276) rounds the remainder to LowestDecimalDigits(left, right). Since fc66077 (#119), CountDecimalDigits (:155) returns -value.Exponent unclamped. PreciseNumber stores 10 as 1E1 and 100 as 1E2, so any integer that ends in 0 is treated as known only to the tens or hundreds place. The remainder is rounded to that place: it either becomes 0, or rounds up to the divisor and the >= |right| guard then turns it into 0.

This has the same root cause as #124, but #124 only describes Add and Subtract, and its acceptance criteria don't cover Mod. A fix limited to those two operators would leave this in place.

Reproduction (HEAD f3c593d, operands from int.ToSignificantNumber())

Expression Result Expected
37 % 10 0 7
1234 % 100 0 34
10 % 3 0 1
100 % 7 0 2
20 % 6 0 2
30 % 7 0 2
7 % 3, 37 % 5 1, 2 correct (no operand ends in 0)

Every integer % 10 or % 100 returns 0, so digit extraction and parity or bucketing checks fail silently. Before fc66077, CountDecimalDigits clamped the count to 0 and all of these returned the correct integer remainder.

Suggested fix

Apply whatever fix #124 settles on (for example, treat values from integer conversions as exact to the units place, or track precision separately as proposed in #120), and make sure Mod goes through it too, since it shares LowestDecimalDigits.

Acceptance criteria

  • 37 % 10 == 7, 1234 % 100 == 34, 10 % 3 == 1, 100 % 7 == 2 for int.ToSignificantNumber() operands.
  • The existing SignificantNumberModTests cases still pass. These include a remainder that rounds up to the divisor giving 0, and the result staying smaller than the divisor.
  • Explicitly coarse values keep the Add/Subtract never round to tens or hundreds: 1.2E3 + 34 = 1234 instead of 1.2E3 #107 behaviour: for example, Parse("1.2E3") % 7 still respects the coarse precision.

Activity

  1. matt-edmondson commented on Oct 19, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    Generated by Claude Code

  2. matt-edmondson commented on Oct 20, 2026

    @matt-edmondson
    ContributorAuthor

    Triage

    An automated sweep looked at this and set it aside before starting. It can't be fixed in isolation, and the interim fix suggested for #124 doesn't meet this issue's acceptance criteria.

    Decision needed: either (a) accept the clamp and give up the #107 tens/hundreds rule for Add/Subtract/Mod until #120 lands, or (b) do #120 first and fix #124 and #135 on top of it. Once that's settled, Mod should go through the same change as #124 so the two can't diverge.

    Left unassigned.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions