Add support for floating-point hex formatting and parsing#124139
Add support for floating-point hex formatting and parsing#124139stephentoub wants to merge 1 commit intodotnet:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds IEEE-754-style hexadecimal floating-point parsing/formatting support across double, float, Half, and BFloat16, exposing it via a new NumberStyles.HexFloat composite and enabling "x"/"X" format specifiers for floating-point ToString/TryFormat.
Changes:
- Introduces
NumberStyles.HexFloatand updates floating-point parse-style validation to permit hex-float parsing while rejecting incompatible flag combinations. - Implements hex-float parsing (
p/Pbinary exponent) and hex-float formatting for"x"/"X"(with optional precision). - Adds extensive unit test coverage for parsing/formatting behavior and updates shared formatter tests to no longer treat
"X"as invalid for floating-point.
Reviewed changes
Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/SingleTests.cs | Adds float hex-float parse/format tests, including rounding/edge cases and custom NumberFormatInfo. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Numerics/BFloat16Tests.cs | Adds BFloat16 hex-float parse/format tests and invalid-input coverage. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/HalfTests.cs | Adds Half hex-float parse/format tests and style-validation checks. |
| src/libraries/System.Runtime/tests/System.Runtime.Tests/System/DoubleTests.cs | Adds extensive double hex-float parse/format tests including boundary/rounding behaviors. |
| src/libraries/System.Runtime/ref/System.Runtime.cs | Exposes NumberStyles.HexFloat in the reference assembly surface. |
| src/libraries/System.Private.CoreLib/src/System/Single.cs | Updates UTF-8 span parse entrypoints to use floating-point style validation (enabling hex-float styles). |
| src/libraries/System.Private.CoreLib/src/System/Numerics/BFloat16.cs | Same validation update for BFloat16 UTF-8 span parse entrypoints. |
| src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs | Adds the hex-float parser and routes AllowHexSpecifier float parsing to it. |
| src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs | Adds "x"/"X" hex-float formatting implementation for floating-point types. |
| src/libraries/System.Private.CoreLib/src/System/Half.cs | Updates UTF-8 span parse entrypoints to use floating-point style validation. |
| src/libraries/System.Private.CoreLib/src/System/Globalization/NumberStyles.cs | Adds the HexFloat composite style with XML documentation. |
| src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs | Adjusts float style validation and introduces new error messages for invalid hex-float/binary combinations. |
| src/libraries/System.Private.CoreLib/src/Resources/Strings.resx | Adds new resource strings for updated validation exceptions. |
| src/libraries/Common/tests/System/RealFormatterTestsBase.cs | Updates shared invalid-format test data to stop treating "X" formats as invalid for floating-point. |
| /// Indicates that the <see cref="AllowLeadingWhite"/>, <see cref="AllowTrailingWhite"/>, | ||
| /// <see cref="AllowLeadingSign"/>, <see cref="AllowHexSpecifier"/>, and <see cref="AllowDecimalPoint"/> | ||
| /// styles are used. This is a composite number style used for parsing hexadecimal floating-point values | ||
| /// as defined in IEEE 754:2008 §5.12.3. |
There was a problem hiding this comment.
The XML doc for NumberStyles.HexFloat states it parses values “as defined in IEEE 754:2008 §5.12.3”, but the implementation/tests also accept forms without a 0x prefix (to support round-tripping ToString("x")) and allow integer-only forms without a p exponent. Please update this documentation to describe the supported syntax (including the optional 0x prefix and when the p exponent is required) or tighten the parser to match the IEEE grammar if strict conformance is intended.
| /// as defined in IEEE 754:2008 §5.12.3. | |
| /// based on the syntax defined in IEEE 754:2008 §5.12.3. The parsed string can include an optional "0x" | |
| /// or "0X" prefix, a hexadecimal significand with an optional decimal point, and an optional binary | |
| /// exponent introduced by 'p' or 'P'. For compatibility, forms without the "0x"/"0X" prefix are also | |
| /// accepted, and integer-only hexadecimal values may omit the 'p'/'P' exponent. |
| // Skip optional "0x" or "0X" prefix (consistent with integer hex parsing) | ||
| if (TChar.CastToUInt32(value[index]) == '0' && | ||
| index + 1 < value.Length && | ||
| (TChar.CastToUInt32(value[index + 1]) | 0x20) == 'x') | ||
| { |
There was a problem hiding this comment.
The comment says skipping an optional 0x prefix is “consistent with integer hex parsing”, but integer parsing with AllowHexSpecifier does not accept a 0x/0X prefix (callers typically strip it themselves). Please reword this comment to reflect the actual intent (e.g., accepting both prefixed and non-prefixed forms for compatibility/round-tripping).
🤖 Copilot Code Review — PR #124139Holistic AssessmentMotivation: Strongly justified — this closes a long-standing api-approved issue (#1630) to add IEEE 754:2008 §5.12.3 hex float formatting/parsing support. This is a standard feature in C/C++ ( Approach: Clean and well-scoped. The implementation adds a dedicated Net positive: This is a clear net positive — it fills a real API gap with a correct, well-tested implementation that follows established patterns. Detailed Findings(Multi-model review: Claude Sonnet 4.5 (primary) + Gemini 3 Pro (secondary). GPT-5.1 timed out and did not contribute. Both contributing models agree on all major points.) ✅ Formatting correctness — verifiedTraced through several representative cases:
NaN/Infinity are handled by the existing pre-check in the shared formatting helper ( ✅ Parsing correctness — verified
✅ Validation logic — correctThe updated
✅ Pre-existing bug fix — ValidateParseStyleInteger → ValidateParseStyleFloatingPointThe UTF-8 ✅ Test coverage — thoroughExtensive tests across all four float types covering: basic values, sign handling, case variations, zero variants, fractional-only significand, leading zeros, trailing decimal point, edge cases (min/max normal, min subnormal, Epsilon), well-known constants (π, e), multiple representations of the same value, overflow to infinity, underflow to zero, round-half-even at multiple boundaries, whitespace handling, optional prefix, integer-only form, custom NumberFormatInfo (comma separator, tilde negative sign), and style validation. Round-trip tests (format then parse) are included for default precision, which is the most important case. 💡 Documentation precision — the existing Copilot review comments about XML doc wording are reasonableThe Similarly, the comment "consistent with integer hex parsing" at the These are minor doc polish items, not blocking. SummaryLGTM. This is a well-implemented feature addition that fills a real API gap. The formatting and parsing logic is correct across all traced edge cases including denormals, rounding boundaries, overflow, and underflow. The code integrates cleanly into the existing |
1 similar comment
🤖 Copilot Code Review — PR #124139Holistic AssessmentMotivation: Strongly justified — this closes a long-standing api-approved issue (#1630) to add IEEE 754:2008 §5.12.3 hex float formatting/parsing support. This is a standard feature in C/C++ ( Approach: Clean and well-scoped. The implementation adds a dedicated Net positive: This is a clear net positive — it fills a real API gap with a correct, well-tested implementation that follows established patterns. Detailed Findings(Multi-model review: Claude Sonnet 4.5 (primary) + Gemini 3 Pro (secondary). GPT-5.1 timed out and did not contribute. Both contributing models agree on all major points.) ✅ Formatting correctness — verifiedTraced through several representative cases:
NaN/Infinity are handled by the existing pre-check in the shared formatting helper ( ✅ Parsing correctness — verified
✅ Validation logic — correctThe updated
✅ Pre-existing bug fix — ValidateParseStyleInteger → ValidateParseStyleFloatingPointThe UTF-8 ✅ Test coverage — thoroughExtensive tests across all four float types covering: basic values, sign handling, case variations, zero variants, fractional-only significand, leading zeros, trailing decimal point, edge cases (min/max normal, min subnormal, Epsilon), well-known constants (π, e), multiple representations of the same value, overflow to infinity, underflow to zero, round-half-even at multiple boundaries, whitespace handling, optional prefix, integer-only form, custom NumberFormatInfo (comma separator, tilde negative sign), and style validation. Round-trip tests (format then parse) are included for default precision, which is the most important case. 💡 Documentation precision — the existing Copilot review comments about XML doc wording are reasonableThe Similarly, the comment "consistent with integer hex parsing" at the These are minor doc polish items, not blocking. SummaryLGTM. This is a well-implemented feature addition that fills a real API gap. The formatting and parsing logic is correct across all traced edge cases including denormals, rounding boundaries, overflow, and underflow. The code integrates cleanly into the existing |
Closes #1630