2016-03-02 5 views
25

In C#:Int32.Parse vs Single.Parse - ("1,234") und ("1,2,3,4"). Warum parsen inter- und Gleitkommatypen Trennzeichen anders?

Int32.Parse("1,234"); 

Dies gilt nicht, das scheint normal:

Dieses eine FormatException wirft, die wie er nicht sollte scheint nur

Single.Parse("1,234"); 

Und überraschend, dass diese parst fein:

Single.Parse("1,2,3,4"); //Returns 1234 

Meine lokale Kultur ist EN-US, daher ist , der Standard Tausender-Trennzeichen.

Hauptfrage: Warum die Inkonsistenz?

Auch: Warum funktioniert Parse("1,2,3,4")? Es scheint nur alle Instanzen des lokalen Trennzeichen vor dem Parsing zu entfernen. Ich weiß, dass es bei einer Regex-Prüfung oder etwas Ähnlichem zusätzlichen Laufzeitaufwand geben würde, aber wann wäre das numerische Literal "1,2,3,4" kein Tippfehler?


Verwandte: C# Decimal.Parse issue with commas

+0

Interessant .. 'Single.Parse (" 1,2,3,4 ", NumberFormatInfo.InvariantInfo);' gibt auch '1234' aus. – Sinatr

+9

Hier gibt es keine Inkonsistenz. 'Int32.Parse()' ist standardmäßig auf 'NumberStyles.Integer' für das zweite Argument festgelegt, das das Tausendertrennzeichen nicht unterstützt. Auf der anderen Seite ist 'Single.Parse()' standardmäßig auf 'NumberStyles.Float | NumberStyles.AllowThousands', was, naja, tausende Separatoren erlaubt. Weitere Informationen finden Sie im Abschnitt Hinweise in [der Dokumentation zu letzterem] (https://msdn.microsoft.com/de-de/library/2thct5cb.aspx). –

+0

@ FrédéricHamidi, das Problem ist drittes Beispiel. Keine Notwendigkeit, die erste oder zweite zu erklären. Können Sie erklären, warum "1,2,3,4" als "1234" -Wert geparst wird? Ich habe jetzt Angst um meine Benutzereingabefelder ... für alle! – Sinatr

Antwort

12

Nach MSDN:

Der Parameter s eine Zahl der Form enthält:

[ws] [Zeichen] Ziffern [ws]


Der s Parameter wird mit dem NumberStyles.Integer-Stil interpretiert. Neben Dezimalstellen sind nur führende und nachfolgende Leerzeichen zusammen mit einem Vorzeichen erlaubt.

Das ist es, NumberStyles.Integer nicht zulässt, das Parse Verfahren die Tausendertrennzeichen zu verwenden, während Single.Parse standardmäßig verwendet NumberStyles.Float und NumberStyles.AllowThousands. Sie können folgende Einzelheiten enthält das zweite Argument als Number dieses Verhalten ändern:

Int32.Parse("1,234", NumberStyles.AllowThousands); //works 

Single.Parse die Gruppierung ignoriert und kulturspezifische nicht NumberGroupSizes überhaupt verwenden und bestimmt nur, wenn der Charakter ist eine Gruppe oder ein Dezimaltrennzeichen. Die Gruppengrößen werden nur beim Formatieren von Zahlen verwendet.

2

Mine ist es-ES Auf diesen. ist das Standard Tausender Trennzeichen und "," das getrennte Zeichen zwischen int und doppeltem So irgendein parse wie "1.2.3.4" gibt mir "123,40" (123.40 auf US) Wenn ich den ". " vor dem "," wie "123,4.3" gibt es Fehler aber, die gleiche Art und Weise die Fragen sagt, wenn ich "1.2.3.4" gebe mir "1234" So kann es sein, ist es eine Funktionalität des .net selbst.

11

Für den ersten Fall von Microsoft Source Code Reference, standardmäßig implementiert Int32.ParseNumberStyles.Integer aber nicht NumberStyles.AllowThousands

public static int Parse(String s) { 
    return Number.ParseInt32(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo); 
} 

So jeder Kommaseparator nicht zulässig ist. Dies:

Int32.Parse("1,234"); 

oder

Int32.Parse("1.234"); 

werden beide falsch sein. In irgendeine Kultur.

Int32.Parse("1,234", NumberStyles.Integer | NumberStyles.AllowThousands); 

Aber

Int32.Parse("1.234", NumberStyles.Integer | NumberStyles.AllowThousands); 

noch throw ein Exception: in EN-US Kultur analysiert werden

es zu beheben, NumberStyles.AllowThousands muss die NumberStyles hinzugefügt werden, die "1.234" ermöglicht.


Für die zweiten Fall nach Microsoft Code Source Reference, ist der Standardstil für Single.Parse:

public static float Parse(String s) { 
    return Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo); 
} 

Welche thousands separator ermöglicht. Und "," wird als Tausendertrennzeichen in EN-US Kultur anerkannt, für Single.Parse und Sie somit den zweiten Fall richtig

Single.Parse("1,234"); //OK 

analysiert erhalten und offensichtlich „1.234“ auch richtig sein, mit der Ausnahme, dass „“ wird nicht als Tausendertrennzeichen, sondern als Dezimaltrennzeichen erkannt.


Was die dritten Fall, Internally, Single.ParseTryStringToNumber Anrufe und Parse.Number, die die Tausendertrennzeichen einfach ignorieren würde. So erhalten Sie:

Single.Parse("1,2,3,4"); //Returns 1234 

Weil es gleichwertig ist wie

Single.Parse("1234"); //Returns 1234 
+1

Sagt das OP nicht 'Int32.Parse (" 1,234 ");' wirft eine 'FormatException' obwohl? – weston