Skip to content

Round exact quotients of approximations to the requested digits [patch] - #141

Merged
matt-edmondson merged 2 commits into
mainfrom
fix/round-approximate-quotients-121
Sep 30, 2026
Merged

matt-edmondson merged 2 commits into
mainfrom
fix/round-approximate-quotients-121

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #121

What changed

Divide(a, b, sd) returns a terminating quotient exactly and doesn't round it. Several paths divided a value that was already rounded to a wider working precision, most often PiTo(working). When that quotient terminated, the caller got the guard digits back as well, and those digits were wrong.

A new private helper, DivideApproximation(numerator, denominator, working, sd), divides at working precision and then calls ReduceSignificance(sd). It is now used on:

  • The paths the issue lists: Asin at ±1, Atan2 with x = 0, DegreesToRadians, and RootN with n < 0. The inner root of RootN(x, -n) is now also computed with RootGuardDigits, so the reciprocal comes from an unrounded root.
  • The other approximation ÷ approximation paths the issue asked to audit: Tan and TanPi (sin/cos), AsinPi, AcosPi, AtanPi and RadiansToDegrees.

Tests

Call Before After
Asin(±1, 5) 1.570796326794895 ±1.5708
Atan2(±1, 0, 5) 1.570796326794895 ±1.5708
DegreesToRadians(180, 5) 3.14159265358979 3.1416
DegreesToRadians(90, 5) (terminating path) 1.5708
RootN(1.0486, -2, 4) 0.9765625 0.9766

These cases are in TestExactQuotientsOfApproximatePiStillRoundToTheRequestedDigits and TestNegativeDegreeRootRoundsTheReciprocalOfAnUnroundedRoot. Both tests failed on main and pass with the fix. The full suite passes: 436 of 436.

This PR is independent of #140 (the Exp2 guard digits). Both come from the same precision-contract audit, but they touch different files.

🤖 Generated with Claude Code

https://claude.ai/code/session_014jNTPLxThrQnZyafw1CZ1p


Generated by Claude Code

Divide returns a terminating quotient exactly. Asin(±1), Atan2(y, 0),
DegreesToRadians and RootN(x, -n) divided a value already rounded to a
wider working precision, so when the quotient terminated they returned
the guard digits too, and those digits were wrong: Asin(1, 5) gave
1.570796326794895 and RootN(1.0486, -2, 4) gave 0.9765625.

Add DivideApproximation, which divides at working precision and then
rounds to significantDigits, and use it on those paths and on the other
approx / approx paths (Tan, TanPi, AsinPi, AcosPi, AtanPi,
RadiansToDegrees). RootN(x, -n) now takes the inner root with guard
digits.

Fixes #121

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014jNTPLxThrQnZyafw1CZ1p
The general paths of AsinPi and AcosPi and all of TanPi had no test,
which left the new DivideApproximation call sites there uncovered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014jNTPLxThrQnZyafw1CZ1p
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit a26dee9 into main Sep 30, 2026
14 checks passed
@matt-edmondson
matt-edmondson deleted the fix/round-approximate-quotients-121 branch September 30, 2026 00:11
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.

Asin(±1), Atan2(y, 0), DegreesToRadians and RootN(x, -n) ignore significantDigits and return wrong trailing digits

2 participants