2012-07-19 21 views
32

Próbuję napisać funkcję, która zasadniczo przekształca tablicę łańcuchów w tablicę ciągów, gdzie wszystkie duble w tablicy są zaokrąglane do liczby dziesiętnych, które ustawiłem. W tablicy mogą być również łańcuchy, które nie są w ogóle podwójnymi wartościami.Łańcuchy parse do podwojenia z przecinkiem i punktem

string[,] values = new string[1, 3]; 

values[0, 0] = "hello"; 
values[0, 1] = "0.123"; 
values[0, 2] = "0,123"; 

int decimalPlaces = 2; 

double tmp; 
string format = "F" + decimalPlaces.ToString(); 
IFormatProvider provider = CultureInfo.InvariantCulture; 
for (int i = 0; i < values.GetLength(0); i++) 
{ 
    for (int j = 0; j < values.GetLength(1); j++) 
    { 
     if (double.TryParse(values[i, j], out tmp)) 
     { 
      values[i, j] = tmp.ToString(format, provider); 
     } 
    } 
} 

Console.ReadLine(); 

Wynik musi być: „cześć”, „0.12”, „0.12”, ale jest „cześć”, „123.00”, „0.12” będzie traktować przecinek w niewłaściwy sposób. Czy ktoś ma proste i wydajne rozwiązanie?

Odpowiedz

26

Chcesz traktować kropkę (.) jako przecinek (,). Tak, wymień

if (double.TryParse(values[i, j], out tmp)) 

z

if (double.TryParse(values[i, j].Replace('.', ','), out tmp)) 
+12

Musisz określić kulturę podczas analizy, w przeciwnym razie będzie działać tylko tam, gdzie aktualna kultura używa "," jako kropka dziesiętna. – hultqvist

+0

Dobrze. Dzięki za ostrzeżenie. – mmdemirbas

+1

Wiem, że wątek jest już dawno martwy, ale zastąpiłbym 'Replace (string, string)' 'replace (char, char)' dla lepszej wydajności ..... – Unknown6656

12

Problem polega na tym, że użytkownik (lub system) nie może odróżnić separatora dziesiętnego od separatora tysięcy, gdy może to być przecinek lub kropka. Na przykład:

W mojej kulturze,

1.123 jest normalny zapis o liczbie powyżej 1000; natomiast

1,123 szereg blisko 1.

za pomocą niezmiennej hodowli użyciem domyślnych kropka jako dziesiętny. Generalnie powinieneś upewnić się, że wszystkie liczby są napisane przy użyciu tej samej stałej kultury we wszystkich systemach (np. W kulturze niezmienniczej).

Jeśli jesteś pewny, że twoje liczby nigdy nie zawierają niczego oprócz przecinka lub kropki dla separatora dziesiętnego (tj. Bez separatorów tysięcy), robiłbym String.Replace() przecinek kropką i robię resztę tak, jak ty.

W przeciwnym razie trudno będzie zaprogramować coś, co odróżni 1.123 od 1,123 bez znajomości kultury.

+0

Zgoda, dla mnie jest to najbardziej logiczne rozwiązanie. Można również sprawdzić, czy ciąg zawiera "," lub "." ale jedno z tych rozwiązań powinno być w porządku imo. – eandersson

0

Można sprawdzić, czy ciąg zawiera kropkę dziesiętną przy użyciu

string s="";

 if (s.Contains(',')) 
     { 
     //treat as double how you wish 
     } 

a następnie potraktować to jako przecinku, w przeciwnym razie po prostu przejść bez podwójną wartość wzdłuż.

79

W leczeniu zarówno i. jako kropki dziesiętnej musisz nie tylko zamieniać jeden na drugi, ale także upewnić się, że w użytym w kulturze procesie parsowania zinterpretowano go jako kropkę dziesiętną.

text = text.Replace(',', '.'); 
return double.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out value); 
+0

Dziękuję, że to zadziałało. –

+0

Pracowałem dla mnie. Chcę tylko, żebym chciała. – radbyx

+0

Najlepsza odpowiedź! Schludny i esay. –

18

NIE POTRZEBUJESZ zastąpienia przecinka i kropki ..

Miałem ten sam problem. Powód jest prosty, kultura konwersji odgrywa dużą rolę w interpretacji przecinka lub kropki. Używam niemieckiej kultury, gdzie przecinek rozróżnia ułamki, gdzie jak wszędzie indziej kropka spełnia swoją funkcję.

Tutaj zrobiłem kompletny przykład, aby różnica była jasna.

string[] doubleStrings = {"hello", "0.123", "0,123"}; 
     double localCultreResult; 
     foreach (var doubleString in doubleStrings) 
     { 
      double.TryParse(doubleString, NumberStyles.Any, CultureInfo.CurrentCulture, out localCultreResult); 
      Console.WriteLine(string.Format("Local culture results for the parsing of {0} is {1}",doubleString,localCultreResult)); 

     } 


     double invariantCultureResult; 
     foreach (var doubleString in doubleStrings) 
     { 
      double.TryParse(doubleString, NumberStyles.Any, CultureInfo.InvariantCulture, out invariantCultureResult); 
      Console.WriteLine(string.Format("Invariant culture results for the parsing of {0} is {1}", doubleString, invariantCultureResult)); 

     } 

wyniki, gdzie po enter image description here

Pobaw się z kulturą, a otrzymasz wynik trzeba.

+0

Próbowałem tego rozwiązania na kilku komputerach z różnymi ustawieniami kultury. Nie działa zgodnie z oczekiwaniami. Później opublikuję inne rozwiązanie. – Andrew

+0

Próbowałem, ale to nie działa dla mnie. zobacz obraz w linku. Parametr CurrentCulture jest tam niemiecki. https://imgur.com/QvtPt7S – batmaci

0

Spróbuj tego ... to działa dla mnie.

double vdouble = 0; 
string sparam = "2,1"; 

if (!Double.TryParse(sparam, NumberStyles.Float, CultureInfo.InvariantCulture, out vdouble)) 
{ 
    if (sparam.IndexOf('.') != -1) 
    { 
     sparam = sparam.Replace('.', ','); 
    } 
    else 
    { 
     sparam = sparam.Replace(',', '.'); 
    } 

    if (!Double.TryParse(sparam, NumberStyles.Float, CultureInfo.InvariantCulture, out vdouble)) 
    { 
     vdouble = 0; 
    } 
} 
+3

Może możesz wyjaśnić nieco, co robisz. "Works for me" nie jest opisowe. – firelynx

0

Rozszerzenie numeru pliku dziesiętnego z ciągu znaków.

  • Bez względu na numer będzie na początku, na końcu lub w środku ciągu.
  • Nie ma znaczenia, czy będzie tylko liczba lub wiele liter "śmieci".
  • Bez względu na to, jaki separator został skonfigurowany w ustawieniach kulturowych na komputerze: będzie on poprawnie analizował kropkę i przecinek.
  • Możliwość ręcznego ustawiania symboli dziesiętnych.

    public static class StringExtension 
    { 
        public static double DoubleParseAdvanced(this string strToParse, char decimalSymbol = ',') 
        { 
         string tmp = Regex.Match(strToParse, @"([-]?[0-9]+)([\s])?([0-9]+)?[." + decimalSymbol + "]?([0-9 ]+)?([0-9]+)?").Value; 
    
         if (tmp.Length > 0 && strToParse.Contains(tmp)) 
         { 
          var currDecSeparator = System.Windows.Forms.Application.CurrentCulture.NumberFormat.NumberDecimalSeparator; 
    
          tmp = tmp.Replace(".", currDecSeparator).Replace(decimalSymbol.ToString(), currDecSeparator); 
    
          return double.Parse(tmp); 
         } 
    
         return 0; 
        } 
    } 
    

Jak używać:

"It's 4.45 O'clock now".DoubleParseAdvanced(); // will return 4.45 
"It's 4,45 O'clock now".DoubleParseAdvanced(); // will return 4.45 
"It's 4:45 O'clock now".DoubleParseAdvanced(':'); // will return 4.45 
+0

4:45 powinno być równe 4,75: P – Logman