You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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.
Priority: High. % on ordinary integer operands silently returns 0 (37 % 10, 10 % 3), with no error. Digit extraction, parity and bucketing all give wrong answers, and the bad results look valid.
Area / suggested assignee:SignificantNumber/SignificantNumber.cs: Mod (:269-276), CountDecimalDigits (:155) and LowestDecimalDigits. Owner: @matt-edmondson
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.
SignificantNumber holds only a PreciseNumber (Value) and has no record of where a value came from. 37.ToSignificantNumber() % 10.ToSignificantNumber() and Parse("37") % Parse("1E1") reach Mod as identical operands. There's nothing for CountDecimalDigits to branch on.
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.
Activity
matt-edmondson commentedon Oct 19, 2026
Triage
%on ordinary integer operands silently returns 0 (37 % 10,10 % 3), with no error. Digit extraction, parity and bucketing all give wrong answers, and the bad results look valid.SignificantNumber/SignificantNumber.cs:Mod(:269-276),CountDecimalDigits(:155) andLowestDecimalDigits. Owner: @matt-edmondsonsum += 2loop stops at 10 #124 (Add/Subtract) and Measured trailing zeros count as insignificant: Parse("1.20") has 2 sig figs, so 1.20 × 1.23456 = 1.5 and 9.81 × 10.0 = 100 #120 (precision tracking). Fixing all three in one change would keepModfrom being left out. No open PR covers it; open PR Return ±1 from (-1).Pow for an integer power beyond double range [patch] #136 touchesPowonly.sum += 2loop stops at 10 #124 fix (clampCountDecimalDigitsto ≥ 0 for values converted from integers) so thatModgoes through the same path, and add the acceptance-criteria cases toSignificantNumberModTests.Generated by Claude Code
matt-edmondson commentedon Oct 20, 2026
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.
SignificantNumberholds only aPreciseNumber(Value) and has no record of where a value came from.37.ToSignificantNumber() % 10.ToSignificantNumber()andParse("37") % Parse("1E1")reachModas identical operands. There's nothing forCountDecimalDigitsto branch on.SignificantNumberAdditionPlaceTestspins"1200" + "34" == 1.2E3(the Add/Subtract never round to tens or hundreds: 1.2E3 + 34 = 1234 instead of 1.2E3 #107 rule from Round sums and differences to tens and hundreds when an operand is that coarse #119), so a parsed1200is deliberately coarse to the hundreds place. ClampingCountDecimalDigitsto>= 0, the interim fix proposed on Regression since #119: integer sums stall at round numbers. 10 + 2 == 10, 100 + 25 == 100, 20 - 3 == 20, and asum += 2loop stops at 10 #124, makes37 % 10 == 7pass. It also drops that Add/Subtract never round to tens or hundreds: 1.2E3 + 34 = 1234 instead of 1.2E3 #107 behaviour for every operand, which breaks this issue's third acceptance criterion and the existing addition-place tests.Decision needed: either (a) accept the clamp and give up the #107 tens/hundreds rule for
Add/Subtract/Moduntil #120 lands, or (b) do #120 first and fix #124 and #135 on top of it. Once that's settled,Modshould go through the same change as #124 so the two can't diverge.Left unassigned.
Generated by Claude Code