Repository navigation
Make calculator % agree with // - #607
YunJ-Chang wants to merge 1 commit into
Conversation
b966b2f to
6469cbe
Compare
The task calculator floors // but used the JavaScript remainder for %, which truncates, so with operands of opposite signs -7 // 3 was -3 while -7 % 3 was -1, and (a // b) * b + a % b no longer gave back a. Floor % so that its result takes the divisor's sign, as Python does. An exact multiple returns 0, since atan2 reads the sign of -0. An infinite divisor keeps the plain remainder, so a finite result stays finite where Python gives inf. Non-negative results and the refusal of a zero divisor stay. Fractional operands can miss the identity because // rounds the quotient first: 1 // 0.1 is 10, and this change adds cases such as (-9.3 // 3.1) * 3.1 + (-9.3 % 3.1), which was -9.3 and is now -6.2, because // stays as it was. Close sysprog21#602 Change-Id: Iab7c91465603f1c4fc4e111d9e89be837e59b8b3
6469cbe to
5be0cfa
Compare
|
Updated at the current head, rebased onto One decision is yours: this change makes |
| const remainder = dividend % divisor; | ||
| if (remainder === 0) return 0; | ||
| if (!Number.isFinite(divisor)) return remainder; | ||
| return remainder < 0 !== divisor < 0 ? remainder + divisor : remainder; |
There was a problem hiding this comment.
A tiny negative dividend with a positive divisor makes remainder + divisor round to exactly divisor: -1e-20 % 3 is 3, and 1e-20 % -3 is -3. That breaks the range promise that the result lies strictly between 0 and the divisor, and (-1e-20 // 3) * 3 + (-1e-20 % 3) is 0 rather than -1e-20. Python gives 3.0 here too, so matching it is defensible, but the doc comment and docs/task-mode.md say the result takes the divisor's sign without mentioning this edge. State it next to the fractional-operand caveat, or return 0 when the sum equals divisor if you prefer to keep the range strict.
| assert.equal(evaluate(text), value, text); | ||
| }); | ||
|
|
||
| test("% leaves a non-negative dividend and divisor alone", () => { |
There was a problem hiding this comment.
Nothing pins the rounding edge in flooredRemainder. Add ["-1e-20 % 3", 3] and ["1e-20 % -3", -3] here, or to a separate test, so whichever behavior you pick (document it or clamp to 0) is locked in and a later "fix" cannot change it unnoticed.
jserv
left a comment
There was a problem hiding this comment.
Rebase the current branch onto the upstream default branch and resolve any conflicts. Run /codetrial-review in AI agents (use $codetrial-review in Codex) and resolve all identified issues. Rework the series into minimal, logically coherent commits, squash closely related commits, and ensure all commit messages follow the project’s rules.
Problem and behavior
The task calculator floors
//but used JavaScript's truncating%, so(a // b) * b + a % bdid not give backawhen the operands had opposite signs. For example,-7 % 3showed -1 while-7 // 3showed -3.This takes approach 1, accepted in #602:
%now returns the remainder of floored division, so its result takes the sign of the divisor. For integers this matches Python.-7 % 3is 2 and7 % -3is -2.//does not change.Notes
The divisor is added only when the signs differ, because
((a % b) + b) % bwould turn0.1 % 1into0.10000000000000009. An exact multiple returns 0 rather than -0, becauseatan2reads the sign. A non-finite divisor keeps the plain remainder, so-1 % 10^400stays -1 where Python givesinf; this differs from Python on purpose, so a finite expression keeps working. Non-negative operands keep their results, and a zero divisor is still refused.docs/task-mode.mdnow states the behavior for negative operands and infinite divisors.The identity is promised for integers while the arithmetic stays exact.
//rounds the quotient before flooring it, so1 // 0.1is 10 where Python gives 9, and that case already failed before this change. This change adds cases of its own:(-9.3 // 3.1) * 3.1 + (-9.3 % 3.1)was -9.3 and is now -6.2, and(5.4 // -1.8) * -1.8 + (5.4 % -1.8)was 5.4 and is now 3.6.%now follows Python there, while-9.3 // 3.1stays -3 where Python gives -4. Deriving//from the remainder, as Python does, would fix this, but it changes1 // 0.1from 10 to 9, which #602 ruled out, so//is unchanged here.Testing
tests/browser/calculator.test.jsadds negative operands, the identity across sign combinations, non-negative results, zero divisors, theatan2case, and infinite divisors. The tests for negative operands, negative zero, and infinite divisors fail without the fix../scripts/test.shpasses; cargo-audit, cargo-deny, actionlint, desktop checks, and one venv-only Python test were skipped locally.Close #602
Summary by cubic
Aligns the calculator's
%with its floored//:%now returns the remainder of floored division, so the result takes the divisor's sign and(a // b) * b + a % bequalsafor integers.-7 % 3is now 2 instead of -1, matching Python, while//and non-negative operands are unchanged.Notes
//rounds the quotient before flooring, so1 // 0.1stays 10 and fractional operands can drift.-1 % 10^400is -1 instead of Python's -inf.Written for commit 5be0cfa. Summary will update on new commits.