Skip to content

fix: Improve upward rounding edge cases for Number::operator/=#7328

Open
ximinez wants to merge 65 commits into
developfrom
ximinez/number-division-accuracy
Open

fix: Improve upward rounding edge cases for Number::operator/=#7328
ximinez wants to merge 65 commits into
developfrom
ximinez/number-division-accuracy

Conversation

@ximinez
Copy link
Copy Markdown
Collaborator

@ximinez ximinez commented May 26, 2026

High Level Overview of Change

Prevents extreme dust rounding from getting lost, especially when rounding away from zero. (Upward for positive, downward for negative.)

Note: This commit was originally pushed to #7051, and resulted in some significant feedback. That feedback has not been addressed, but will be ASAP.

Also Note: I'd like to try to get this into 3.2 if only to avoid needing to create another amendment gate the change. However, 3.3 is fine if necessary.

Context of Change

If there is still a remainder after the correctionFactor used in Number division is processed, pass a flag to doNormalize which will set the "x-bit", indicating that non-zero digits have been dropped off the end of the number, which will round the unsigned mantissa up if:

  • The number is positive, and rounding is Upward
  • The number is negative, and rounding is Downward
  • Rounding is "ToNearest", and aside from the "x-bit" the remainder is exactly 0.5. This is sort of a 0.5+epslion scenario, so the nearest value will be the next one up.

The remainder is always rounded away, since large-mantissa Number is limited to 19 significant digits (~2^64), but in extreme cases, the rounding can go in the wrong direction.

Also refactors the computation so that the factors used are consistent across the various mantissa scales, but the math is otherwise exactly the same.

Before / After

Example from the unit test:

xrpl.basics.Number operator/= Upward on Large returns value < truth 

  a                 = 2
  b                 = 1000000000000000007
  exact a/b         = 1.999999999999999986000000000000000098e-18

Note that for this test, Number is rounding upward. The first 19-digits of the result are 1999999999999999986. The remaining digits are 000000000000000098.

Before:

The correction computation only finds 000 which didn't meaningfully modify the original result, such that even though rounded "up", the resulting mantissa remained 1999999999999999986.

After:

The correction computation finds still finds 000, but determines there is still some remainder left after accounting for that. Thus after rounding upward the resulting mantissa is the correct 1999999999999999987 value.

  stored a/b        = 1.999999999999999987e-18

ximinez and others added 30 commits May 6, 2026 22:49
- Add helper function, doDropDigit, to wrap the common pattern:
    push(mantissa % 10);
    mantissa /= 10;
    ++exponent;
- Might have been helpful to catch this issue when developing.
- Refactor the Guard decision in withTxnType into createGuards, which
  lives in Rules.cpp. It is physically located near
  setCurrentTransactionRules, and documented to explain that changes
  need to be synchronized.
- Some EscrowToken tests used a hard-coded list of amendments to
  determine whether to expect large mantissa logic. That ignored the
  effects of fixCleanup3_2_0, especially as applied to the previous fix
  affecting preflight, preclaim, etc.
- Add a helper function, useRulesGuards, which will return the same
  decision as createGuards and setCurrentRulesImpl. Use that helper
  function in the relevant tests.
- Also remove an #include that clang-tidy was complaining about.
…maxrepcusp

* XRPLF/develop:
  release: Set version to 3.3.0-b0 (7280)
  refactor: Rename static constants (7120)
  refactor: Use `isFlag` where possible instead of bitwise math (7278)
  ci: Update XRPLF/actions (7281)
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
- Removes one int64 to 128 conversion
Copy link
Copy Markdown
Contributor

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues.

Review by Claude Opus 4.6 · Prompt: V15

Copy link
Copy Markdown
Contributor

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues.

Review by Claude Opus 4.6 · Prompt: V15

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

Comment thread include/xrpl/basics/Number.h Outdated
Comment thread src/libxrpl/basics/Number.cpp
Copy link
Copy Markdown
Contributor

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues.

Review by Claude Opus 4.6 · Prompt: V15

Copy link
Copy Markdown
Contributor

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues.

Review by Claude Opus 4.6 · Prompt: V15

Comment thread src/libxrpl/basics/Number.cpp Outdated
Comment thread src/libxrpl/basics/Number.cpp Outdated
Comment thread src/libxrpl/basics/Number.cpp
Comment thread src/libxrpl/basics/Number.cpp
ximinez added 4 commits May 28, 2026 17:46
- Add missing headers.
- Improve code coverage exclusions.
- Clean up several variable names.
- Improve explanatory comments.
- Remove the switch statement from MantissaRange::getMin. Change it to
  a straight power of ten lookup.
- Demonstrates the incorrect "before" behavior
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

Comment thread include/xrpl/basics/Number.h
Comment thread src/test/basics/Number_test.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Collaborator

@Tapanito Tapanito left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Copy link
Copy Markdown
Contributor

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues.

Review by Claude Opus 4.6 · Prompt: V15

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comment thread src/libxrpl/basics/Number.cpp
Comment thread src/test/basics/Number_test.cpp Outdated
Comment thread src/test/basics/Number_test.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues.

Review by Claude Opus 4.6 · Prompt: V15

- Downward with a negative result, and ToNearest with a remainder
  slightly larger than 0.5.
Copy link
Copy Markdown
Contributor

@xrplf-ai-reviewer xrplf-ai-reviewer Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues.

Review by Claude Opus 4.6 · Prompt: V15

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.

3 participants