Laden...

string und double.TryParse = Komma verschiebung?

Erstellt von lord_fritte vor 15 Jahren Letzter Beitrag vor 14 Jahren 9.432 Views
L
lord_fritte Themenstarter:in
553 Beiträge seit 2007
vor 15 Jahren
string und double.TryParse = Komma verschiebung?

Hallo ich möchte aus einem String einen double Parsen, hier ein kleiner Codeausschnitt:


string s = "5.7889";
double d = 0.0;
if (double.TryParse(s, out d))
  Console.WriteLine(d.ToString());
else
  Console.WriteLine("Ungültig");

Als Ergebnis kommt aber raus: 57889, jetzt bin ich aber mal mit dem Debugger durch gegangen und es ist schon ein double, aber das Komma wurde ganz ans Ende Verschoben: 57889.0, lässt sich das Verhindern?

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo lord_fritte,

du musst beim Parsen die richtige CultureInfo verwenden, in der Dezimal- und Tausendertrenner passend festgelegt sind. Hier vermutlich InvariantCulture.

herbivore

1.002 Beiträge seit 2007
vor 15 Jahren

Hallo lord_fritte,

das gleiche Problem hatte ich auch (wusste aber nichts von der CultureInfo), habe ein kleines WorkAround gebastelt ...
Sag Bescheid, wenn du Interesse hast ...

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

3.971 Beiträge seit 2006
vor 15 Jahren

Hallo m0rius,
rein aus Interesse, zeig doch mal dein "Workaround"

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

4.221 Beiträge seit 2005
vor 15 Jahren

Ist sicher ein string Replace von . durch ,

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

1.002 Beiträge seit 2007
vor 15 Jahren

Hallo kleines_eichhoernchen,

geht sicher schöner, läuft aber. Ist ebenfalls im Rahmen meiner Info-Hausarbeit entstanden, darum auf deutsch und extrem auskommentiert.

// Konvertiert einen String in einen Double-Wert
		public static double ToDouble(string wert)
		{
			// Whitespace entfernen
			wert = wert.Trim();
			
			bool positiv = true;
			
			// Wenn negativ, vermerken und Minuszeichen entfernen
			if (wert.IndexOf("-") == 0)
			{
				positiv = false;
				wert = wert.Replace("-", "");
			}
			
			double faktor;
			
			// Kein Komma vorhanden (bzw. Punkt)?
			if (wert.IndexOf(".") < 0)
			{
				faktor = Convert.ToDouble(wert);
			}
			
			// Komma vorhanden!
			else
			{
				String[] unterteile = wert.Split('.');
				
				// Alle Nachkommastellen durchgehen und Schluss-Nullen entfernen
				while (unterteile[1].LastIndexOf('0') == unterteile[1].Length - 1 && unterteile[1].Length > 1)
				{
					// String um das letzte Zeichen verkürzen
					unterteile[1] = unterteile[1].Substring(0, unterteile[1].Length - 1);
				}
				
				// Wenn der Faktor 0 ist, Rechnung vermeiden
				if (unterteile[1].Length == 0)
				{
					faktor = 0;
				}
				
				// Faktor ist zum Glück nicht 0
				else
				{
					faktor = Convert.ToDouble(unterteile[0]) +
						Convert.ToDouble(unterteile[1]) / Math.Pow(10, unterteile[1].Length);
				}
			}
			
			// Evtl. Faktor negieren
			if (!positiv)
			{
				faktor *= -1;
			}
			
			return faktor;
		}

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo m0rius,

geht sicher schöner

genau, eben mit der schon genannten CultureInfo. 😃 Wenn man die passend zum Zahlenformat im String wählt, kann man die Konvertierung mit einem Aufruf von Convert.ToDouble erledigen.

herbivore

L
lord_fritte Themenstarter:in
553 Beiträge seit 2007
vor 15 Jahren

Und wo baue ich das CultureInfo ein?

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo lord_fritte,

mal abgesehen davon, dass du das leicht selbst über die Forensuche hättest herausfinden können, steht es doch im Prinzip schon in meinen Antworten.

herbivore

J
3.331 Beiträge seit 2006
vor 15 Jahren

Außerdem hast Du die Frage mit double.TryParse begonnen. :rtfm: zeigt dazu eine Alternative mit Beispiel.

Sowenig Eigeninitiative 🙄

Jürgen

L
lord_fritte Themenstarter:in
553 Beiträge seit 2007
vor 15 Jahren

Doch ich habs jetzt gefunden, sorry.
Also es geht jetzt so:


NumberStyles style = NumberStyles.AllowDecimalPoint;
          CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
          string s = "5.7889";
          double d = 0.0;
          if (double.TryParse(s, style, culture, out d))
            Console.WriteLine(d.ToString());
          else
            Console.WriteLine("Ungültig");

Danke.

4.221 Beiträge seit 2005
vor 15 Jahren

Statt en-US nimmste besser die InvariantCulture

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

L
lord_fritte Themenstarter:in
553 Beiträge seit 2007
vor 15 Jahren

Ah also das heißt er geht nicht nach Landesspezifischen Reglen vor, sondern allgemein nach dem was für C# gilt?

5.742 Beiträge seit 2007
vor 15 Jahren

Hallo lord_fritte,

du bist heute wohl Doku-scheu. 🙂

sondern allgemein nach dem was für C# gilt?

Nein, eher das, was international gilt:


>

Ruft die kulturunabhängige (invariante) CultureInfo ab. [...] Sie ist der englischen Sprache zugeordnet, aber ohne Bezug auf ein Land oder eine Region. Sie wird in fast allen Methoden im Globalization-Namespace verwendet, die eine Kultur erfordern.

L
lord_fritte Themenstarter:in
553 Beiträge seit 2007
vor 15 Jahren

Ja das meinte ich doch, also er behandelt ihn so, wie auch der compiler ihn behandeln würde.

5.742 Beiträge seit 2007
vor 15 Jahren

Ja das meinte ich doch, also er behandelt ihn so, wie auch der compiler ihn behandeln würde.

Dann lasse mal vom C# Compiler die Zahl

1,000,000.4

interpretieren...

3.971 Beiträge seit 2006
vor 15 Jahren

Größter Unterschied zwischen der Kultur en-US und InvariantCulture ist der dass sich die Kultur (Zahlenformatierung, Datumsformatierung, Maßeinheiten) jederzeit ändern können.

en-US ist derzeit aber der InvariantCulture sehr ähnlich. Zur Abspeicherung von Daten (in Xml, CSV) sollte die InvariantCulture genommen werden, da ansonsten wenn sich die Kultur mal ändern sollte, die entsprechenden Dateien fehlerhaft sind und nicht mehr eingelesen werden können.

Die Kultur en-US (oder jede andere Länder- und Regionsabhängige Kulture) wird nur zur Ausgabe am Bildschirm, Drucker oder in diversen Dokumenten(PDF, Excel, Doc) verwendet.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

U
1.688 Beiträge seit 2007
vor 15 Jahren

Hallo m0rius,

geht sicher schöner, läuft aber.

ähem - allerdings nicht korrekt. Aus "1.0" und ähnlichen wird z. B. 0. Von "gemeineren" Varianten wie ".1" mal ganz abgesehen.

1.002 Beiträge seit 2007
vor 15 Jahren

Hallo ujr,

danke für den Hinweis, ist gefixt (die "gemeine" Variante ist in meinem Projekt syntaktisch nicht erlaubt, und nur dort verwende ich die Methode).

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo m0rius,

[Fehler] ist gefixt

wieder mal ein schönes Beispiel, warum man Dinge, die das Framework bietet nicht nachprogrammieren sollte. Das ist zwar oft schnell gemacht, aber bis man alle Fehler draußen hat, dauert es. Das Framework ist dagegen schon sehr ausgiebig getestet und erprobt. Wenn das Framework also schon eine Lösung bietet, sollte man die auch verwenden.

herbivore

L
lord_fritte Themenstarter:in
553 Beiträge seit 2007
vor 14 Jahren

Ich habe ein neues Problem, Codestück:


NumberStyles style = NumberStyles.AllowDecimalPoint;
CultureInfo culture = CultureInfo.InvariantCulture;

string sFormat = "-5.447";
bool bRes = double.TryParse(sFormat, out dDouble);

leider lassen sich keine negativen Zahlen, egal ob mit . oder ohne, lassen sich nicht parsen, es kommt immer false und 0.0 zurück..

J
3.331 Beiträge seit 2006
vor 14 Jahren

Du musst eben auch NumberStyles.AllowLeadingSign festlegen. Jürgen

L
lord_fritte Themenstarter:in
553 Beiträge seit 2007
vor 14 Jahren

Ja wenn ich das aber dazu nehmen, wir das Komma wieder ans ende geschoben...

EDIT: Achja falscher Code, ist natürlich so: double.TryParse(sFormat, style, culture, out dDouble);

EDIT2 Ok ich habs, AllowLeadingSign muss vor AllowDecimalPoint. danke.

U
1.688 Beiträge seit 2007
vor 14 Jahren

Hallo,

was meinst Du mit "muss vor"?

Übrigens, NumberStyles.Float schließt diese und weitere Formatangaben ein - vielleicht willst Du das ja nehmen, falls es mal Exponenten gibt.