Repository navigation
Truncate Python integer division in integer arithmetic so long quotients stay exact [patch] - #206
Merged
Merged
Conversation
…nts stay exact [patch] Integer `/` and `%` were lowered to `int(a / b)` and `a - b * int(a / b)`. Python's `/` is true division and returns a float, so for a long above 2^53 the quotient was rounded before it was truncated: `n % 7` on 1700000000123456789 returned -75 instead of 2. The quotient is now `a // b` when the operands share a sign and `-(-a // b)` when they don't, which truncates toward zero without leaving integer arithmetic. The remainder is `a - b * quotient` as before. Operands that are not safe to read twice are still bound once through a lambda. Fixes #192 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CkCrYLchcFZxtGF9DyXZHi
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Fixes #192
What changed
PythonGenerator.GenerateBinarylowered integer/toint(a / b)and integer%toa - b * int(a / b). Python's/always returns a float. For alongabove 2^53 the quotient was rounded before it was truncated, so the quotient came out wrong and the remainder could come out negative. For example,n % 7withn = 1700000000123456789returned-75instead of2.The quotient is now truncated using integer arithmetic only:
When the operands share a sign, flooring and truncating agree. When they don't, negating the dividend turns floor division into truncation. The remainder is still
a - b * <quotient>. As before, an operand that is a variable or a literal is written inline, and anything else (such as a call) is bound once through a lambda. TheIntegerDivisionTestscall-count assertion still checks that.intoperands get the same lowering. It is exact for them too, and one form for both keeps the generator simple.Tests (
IntegerDivisionTests)Python_LongOperandsAbove2To53_MatchTheCFamilyruns the generated Python and compares it with C#'s/and%. It covers:longoperands passed as parameters, through a call operand (the lambda path), and as the issue's repro (long n = 1700000000123456789; return n % 7)9007199254740993 / 1,long.MaxValue, andlong.MinValue + 1The test module starts with
long = int, because the generator still writeslongas an undefined annotation (#109, open PR #124). That keeps this test about the arithmetic.With the generator change reverted, the test fails on its first check:
div_long_literal() = 242857142874779552, expected 242857142874779541. With the change, the existingPython_MatchesTheCFamilycases still pass, and the full suite passes (1116/1116).The JavaScript side (
longvalues outside ±(2^53−1)) is a separate issue, #168, and is not touched here.🤖 Generated with Claude Code
https://claude.ai/code/session_01CkCrYLchcFZxtGF9DyXZHi
Generated by Claude Code