Skip to content

Convert NFloat in CreateChecked, CreateSaturating, CreateTruncating and To() [patch] - #173

Merged
matt-edmondson merged 1 commit into
mainfrom
fix/138-nfloat-conversions
Oct 20, 2026
Merged

matt-edmondson merged 1 commit into
mainfrom
fix/138-nfloat-conversions

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #138

What was wrong

TryConvertFrom and TryConvertTo handled every built-in numeric type except System.Runtime.InteropServices.NFloat. For NFloat:

  • CreateChecked, CreateSaturating and CreateTruncating threw NotSupportedException in both directions.
  • To<NFloat>() fell back to NFloat.CreateChecked(BigInteger), which also throws, even for 1.5.

ToPreciseNumber() already accepted NFloat, so the API took NFloat in but refused to give it back.

Change

  • From NFloat: routed through TryConvertFromBinaryFloatingPoint, the same path double, float and Half use, with the same NaN and infinity rules. The result matches ToPreciseNumber().
  • To NFloat: rounded once, through ToSingle() when NFloat.Size is 4 and ToDouble() otherwise. It is correctly rounded on either platform and overflows to infinity like the other binary floats. To<NFloat>() picks this up because it calls TryConvertTo first.
  • To<T>() remarks: NFloat is now listed with the correctly rounded types. The remarks also say that the fallback for any other type needs CreateChecked from BigInteger and double, or it throws NotSupportedException. The issue offered either documenting this or making the fallback work; I documented it.
  • Docs: the TryConvertToChecked remarks and the conversions bullet in CLAUDE.md now mention NFloat.

Tests

New tests in PreciseNumberConversionTests:

  • FromNFloatMatchesToPreciseNumber: all three modes for 1.5, -0.3048 and 0. For 0.1, Epsilon (denormal), MaxValue and MinValue, CreateChecked agrees with ToPreciseNumber(). Also covers NaN (throws when checked, gives 0 when saturating) and infinity (throws).
  • ToNFloatIsCorrectlyRounded: 1.5 and 0.1 in all modes and through To<NFloat>(). Values beyond range give ±infinity, and values below it give 0.
  • NFloatRoundTripsThroughPreciseNumber: 1.5, 0.1, Epsilon, MaxValue, MinValue and 1/3 round-trip through all three modes and To<NFloat>().

With the PreciseNumber.Conversions.cs change reverted, all 3 fail. With it, the full suite passes locally on net10.0 (516/516). The library also builds for net7.0 through net10.0.


Generated by Claude Code

…nd To() [patch]

TryConvertFrom and TryConvertTo recognised every built-in numeric type
except NFloat, so the generic Create* conversions threw
NotSupportedException in both directions, and To<NFloat>() fell back to
NFloat.CreateChecked(BigInteger), which throws too. ToPreciseNumber()
already accepted NFloat. NFloat now goes through the same binary floating
point path as double, float and Half: coming in, with the same NaN and
infinity rules; going out, correctly rounded to float or double,
whichever NFloat.Size says it is. The To<T>() remarks now say the
fallback for other types needs CreateChecked from BigInteger and double.

Fixes #138

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

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit 2f000e4 into main Oct 20, 2026
15 checks passed
@matt-edmondson
matt-edmondson deleted the fix/138-nfloat-conversions branch October 20, 2026 01:15
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.

To<NFloat>(), NFloat.CreateChecked(x) and PreciseNumber.CreateChecked(nfloat) throw NotSupportedException, although ToPreciseNumber() accepts NFloat

2 participants