Skip to content

Parse("1 234,5", fr-FR) throws where decimal returns 1234.5: a typed space doesn't match a no-break-space group separator #174

Open

Description

@matt-edmondson

What's wrong

Many cultures use a no-break space as the group separator:

  • U+202F narrow no-break space: fr-FR
  • U+00A0 no-break space: ru-RU, pl-PL, sv-SE, cs-CZ, nb-NO, fr-CA, and others

Parse matches the group separator by ordinal comparison only:

// Group separators may only sit between integral digits.
if (allowThousands && !hasDecimal && digitCount > 0 && s[i..].StartsWith(groupSeparator, StringComparison.Ordinal))
{
i += groupSeparator.Length - 1;
continue;

if (allowThousands && !hasDecimal && digitCount > 0 && s[i..].StartsWith(groupSeparator, StringComparison.Ordinal))

That means a number typed with an ordinary space (U+0020), which is what a keyboard produces, is rejected.

Every BCL numeric type accepts it. The runtime's number parser deliberately treats U+0020 as matching a U+00A0 or U+202F separator (IsSpaceReplacingChar / MatchChars in Number.Parsing.cs), so decimal, double, and int all parse these strings. Generic code calling INumberBase<T>.Parse(s, provider) therefore works for every built-in type and fails only for PreciseNumber. That includes the provider-only overloads, which use NumberStyles.Any.

PreciseNumberParseCultureTests covers a U+202F separator (NarrowSpaceGroups), but only to round-trip the library's own output. It has no case for typed input.

Reproduction (net10.0, NumberStyles.Number; Any and AllowThousands behave the same)

All inputs below use a plain U+0020 space between digit groups.

Culture (group separator) Input decimal PreciseNumber
fr-FR (U+202F) "1 234,5" 1234.5 FormatException
fr-FR "-1 234 567" -1234567 FormatException
ru-RU / pl-PL / cs-CZ / fr-CA (U+00A0) "1 234,5" 1234.5 FormatException
sv-SE / nb-NO (U+00A0) "-1 234 567" -1234567 FormatException
fr-FR, input with a real U+202F "1 234,5" 1234.5 1234.5 (works)
de-CH (U+2019) "1 234,5" fails fails (agree)
var fr = new CultureInfo("fr-FR");
decimal.Parse("1 234,5", fr);          // 1234.5
PreciseNumber.Parse("1 234,5", fr);    // FormatException

Suggested fix / acceptance criteria

Activity

  1. matt-edmondson commented on Oct 20, 2026

    @matt-edmondson
    ContributorAuthor

    Triage


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions