Skip to content

Read white space around a sign or currency symbol as the BCL does [patch] - #191

Merged
matt-edmondson merged 3 commits into
mainfrom
fix/189-white-around-sign
Nov 11, 2026
Merged

matt-edmondson merged 3 commits into
mainfrom
fix/189-white-around-sign

Conversation

@matt-edmondson

Copy link
Copy Markdown
Contributor

Fixes #189

What was wrong

StripLeadingAffixes and StripTrailingAffixes trimmed no white space after a leading sign or before a trailing sign. A value formatted with NumberNegativePattern 2 (- 1,234.50) or 4 (1,234.50 -) therefore could not be parsed back with the same format provider. decimal reads "5 -", "$\t5" and "$- 5", but these were rejected here. In the other direction, CurrencySymbolSpaces included an ordinary space. That made "$ 5" parse under AllowCurrencySymbol | AllowLeadingSign, where the BCL rejects it.

Change

The rules follow Number.TryParseNumber's affix loops, and I checked each case against decimal before encoding it.

  • Trailing side: with AllowTrailingWhite, white space is trimmed after removing a trailing sign or currency symbol.
  • Leading side: with AllowLeadingWhite, white space is trimmed after a leading currency symbol. After a sign or opening parenthesis, it is trimmed only if a currency symbol has already been read or NumberNegativePattern == 2. This is why - 5 is rejected under the invariant culture and accepted under pattern 2, as in the BCL.
  • No white-space flag: white space next to an affix is rejected.
  • Same set as before: "white space" is the set TrimAllowedWhite already uses.
  • Rendered spaces kept: CurrencySymbolSpaces now holds only U+00A0 and U+202F. These are still accepted next to a currency symbol under any style, so the existing TestParseAcceptsANoBreakSpaceBeforeACurrencySymbol leniency is kept.

Tests

New rows in PreciseNumberParseAffixTests. Each case first asserts what decimal does with the same text, style and format.

  • Accepted, matching decimal:
    • "5 -", "5\t-", " 5 - ", "5 +" and "1,234.50 -" under Number
    • "- 5" and "- 1,234.50" under pattern 2
    • "( 5)" and "(5 )" with parentheses
    • "$\t5", "5\t$", "$- 5", "$ - 5", "-$ 5", "5 $ -" and "5 - $" under Currency
  • Rejected, matching decimal:
    • "- 5" and "+ 5" under the invariant culture with Number
    • "- $5" under Currency
    • "$ 5", "$- 5" and "-$ 5" under AllowCurrencySymbol | AllowLeadingSign
    • "5 $" under AllowCurrencySymbol | AllowTrailingSign
  • Round trip: TestParseReadsBackEveryNumberNegativePattern reads ToString("N2", nf) back for patterns 0–4. Pattern 0 writes (n), which only AllowParentheses reads, for decimal as well, so that case adds the flag.

With the library change stashed, 21 of the 57 affix tests fail. With it, the full suite passes: 618/618.


Generated by Claude Code

…tch]

Parse trimmed no white space between the digits and a trailing sign, or
after a leading sign, so a value written with NumberNegativePattern 2
("- 1,234.50") or 4 ("1,234.50 -") couldn't be read back with the same
format, and "5 -", "$\t5" and "$- 5" failed where decimal reads them.
An ordinary space next to a currency symbol was taken under any style,
so "$ 5" parsed though no white-space flag allowed it.

White space is now taken where the BCL takes it: among the trailing
affixes under AllowTrailingWhite, and under AllowLeadingWhite after a
leading currency symbol, or after a sign or opening parenthesis once a
currency symbol has been read or when the negative pattern is 2. The
rendered no-break spaces next to a currency symbol stay accepted under
any style.

Fixes #189

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vfJW2U6qwK2oTLt2cfE7k
SonarCloud put StripLeadingAffixes' cognitive complexity at 17 against
an allowance of 15 once it trimmed white space after a sign. The trim
after a sign and the choice of what to trim beside a currency symbol
are now their own helpers; behaviour is unchanged.

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

# Conflicts:
#	PreciseNumber.Test/PreciseNumberParseAffixTests.cs
@sonarqubecloud

Copy link
Copy Markdown

@matt-edmondson
matt-edmondson merged commit d0ec18d into main Nov 11, 2026
15 checks passed
@matt-edmondson
matt-edmondson deleted the fix/189-white-around-sign branch November 11, 2026 00:56
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.

Parse can't read its own N output for NumberNegativePattern 2 and 4: "1,234.50 -" and "5 -" fail, though decimal, double and int parse them

2 participants