Skip to content

literal: round-half-even tie for normal-range float/complex repr#8243

Open
youknowone wants to merge 1 commit into
RustPython:mainfrom
youknowone:float-repr-tie
Open

literal: round-half-even tie for normal-range float/complex repr#8243
youknowone wants to merge 1 commit into
RustPython:mainfrom
youknowone:float-repr-tie

Conversation

@youknowone

@youknowone youknowone commented Jul 8, 2026

Copy link
Copy Markdown
Member

float::to_string's normal-magnitude branch and complex::component_to_string returned Rust's shortest formatting directly. Rust's formatter can land on the odd-digit neighbour of a rounding tie where repr()'s round-half-to-even picks the even one, e.g. bits 0x42e26687db6b9b04 format as 161852602146008.13 but CPython repr gives 161852602146008.12 (both round-trip).

The scientific branch of float::to_string already ran through prefer_cpython_tie_repr; this extends that helper to fixed-notation strings and applies it to the normal-magnitude float branch and to both complex branches.

Verified against CPython 3.14 over a differential battery (20k floats, 280k complex pairs incl. subnormals / powers of ten / ties): 0 divergences after the fix. Added a normal-range tie unit test.

assisted by Claude

Summary by CodeRabbit

  • Bug Fixes
    • Improved repr()/str() formatting for floating-point values in round-half-to-even tie cases, including normal-range and scientific-notation outputs.
    • Enhanced complex number formatting so real/imaginary components reflect the expected tie digit behavior, including signed zero scenarios.
    • Improved handling of decimal inputs lacking an exponent when generating representations.
  • Tests
    • Added exact repr() assertions for built-in float and complex edge cases covering positive/negative components and tie behavior.

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yml

Review profile: CHILL

Plan: Pro

Run ID: 6e1841e6-581f-46a6-bd3b-11ebac6813bd

📥 Commits

Reviewing files that changed from the base of the PR and between 374d562 and e526090.

📒 Files selected for processing (4)
  • crates/literal/src/complex.rs
  • crates/literal/src/float.rs
  • extra_tests/snippets/builtin_complex.py
  • extra_tests/snippets/builtin_float.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • crates/literal/src/complex.rs
  • extra_tests/snippets/builtin_complex.py
  • extra_tests/snippets/builtin_float.py

📝 Walkthrough

Walkthrough

Float and complex repr formatting now route through prefer_cpython_tie_repr, which is pub(crate) and handles exponent-less inputs. parse_decimal_rational accepts strings without 'e'. Rust and Python tests cover tie-breaking output.

Changes

CPython-compatible tie repr formatting

Layer / File(s) Summary
Tie-repr helper and exponent parsing
crates/literal/src/float.rs
prefer_cpython_tie_repr becomes pub(crate) and computes a boundary from 'e' or the string end; parse_decimal_rational treats missing 'e' as exponent 0.
Apply tie-repr in float and complex formatting
crates/literal/src/float.rs, crates/literal/src/complex.rs
to_string and component_to_string now pass formatted literals through prefer_cpython_tie_repr instead of returning them directly.
Tie-behavior tests
crates/literal/src/float.rs, extra_tests/snippets/builtin_float.py, extra_tests/snippets/builtin_complex.py
Adds a Rust unit test and Python snippet assertions for tie and non-tie float and complex formatting outputs.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • RustPython/RustPython#7634: Both PRs modify the same f64 component string generation logic in crates/literal/src/complex.rs used for complex repr formatting.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: round-half-even tie handling for normal-range float and complex repr output.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

}

#[test]
fn repr_normal_range_uses_cpython_tie_digit() {

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Add also extra_tests

@youknowone youknowone marked this pull request as ready for review July 9, 2026 09:06
to_string's normal-magnitude branch and complex::component_to_string
returned Rust's shortest formatting directly, which can pick the odd-digit
neighbour of a rounding tie where repr() picks the even one (e.g. bits
0x42e26687db6b9b04 formats as 161852602146008.13 vs repr's ...08.12).
Route both through prefer_cpython_tie_repr, generalized to fixed-notation
strings. Add unit tests and float/complex repr snippet tests.

Assisted-by: Claude
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.

1 participant