float.TryParse i inny decimal separator

0

Cześć, sprawdziłem CultureInfo.CurrentUICulture.NumberFormat i WSZYSTKIE decimalseparatory mam ustawione na przecinek.
Tymczasem kod taki:

string s = "12,55";
float f;
bool b = float.TryParse(s, out f);

zwraca TRUE, ale zmienna f ma wartość 1255.
Dopiero jak zmienię przecinek na kropkę, to jest dobrze. Czemu tak jest? Co ciekawe, na innym komputerze (też z Windows 10) wszystko działa poprawnie.

0

A ustawienia daty w Windowsie sprawdzałeś? :) Miałem podobny problem, gdzie u siebie datę miałem chyba w formacie DD/MM/YYYY a inni mieli DD.MM.YYYY i były różnice :P

0

Jeśli masz Windowsa 7 wejdź do Panelu Sterowania -> Region i Język -> Ustawienia dodatkowe i tam masz symbol dziesiętny - jeśli wpiszesz przecinek ,
to

            float f;
            bool b = float.TryParse(s, out f);
            Console.WriteLine(f);

da wynik 12,55

jeśli ustawisz symbol dziesiętny na kropkę to wynik będzie - 0 , wtedy musisz zmienić string s = "12.55"; i wynik też będzie z kropką

Jeśli u ciebie jest inaczej to zresetuj ustawienia w Windowsie

Pozdrawiam ;)

0

miało być

string s = "12,55";
           float f;
           bool b = float.TryParse(s, out f);
           Console.WriteLine(f);

da wynik 12,55

1
string s = "12,55";
float f;
bool b = float.TryParse(s, NumberStyles.Any, CultureInfo.GetCultureInfo("pl-PL"), out f);
Console.WriteLine(b + " " + f);

True 12,55

string s = "12.55";
float f;
bool b = float.TryParse(s, NumberStyles.Any, CultureInfo.GetCultureInfo("pl-PL"), out f);
Console.WriteLine(b + " " + f);

False 0

Podsumowując:

InvariantCulture – używamy do zapisu i odczytu danych oraz do operacji wew. programu. Mamy wtedy pewność, że format na którym pracujemy jest jednolity.

InvariantCulture nie jest żadną konkretną reprezentacją jakiejś jednej kultury. Jest to raczej najbardziej standardowa i ujednolicona forma formatowania oparta na kulturze typu „en-US” (ale nie jest taka sama)

CultureInfo.CurrentCulture – używamy gdy chcemy sformatować dane od użytkownika na przykład z formularzy itd. Odczytywanie CurrentCulture nie zawsze jest prawdziwe i trzeba na to zwrócić uwagę.

Specyficznych kultur używamy gdy chce na siłę wymusić format na przykład wyświetlając dane użytkownikowi końcowemu.

src http://blogprogramisty.net/cultureinfo-w-c/

0

Możesz jeszcze tak zrobić :

  string s = "12.55";
            float f;
            CultureInfo kultura = new CultureInfo("pl-PL");
            kultura.NumberFormat.CurrencyDecimalSeparator = ".";
            bool b = float.TryParse(s, NumberStyles.Any, kultura, out f);
            Console.WriteLine(b + " " + f);
0

Albo lepiej

string s = "12.55";
            float f;
            CultureInfo kultura = new CultureInfo("pl-PL");
            kultura.NumberFormat.NumberDecimalSeparator = ".";
            bool b = float.TryParse(s, NumberStyles.Any, kultura, out f);
            Console.WriteLine(b + " " + f.ToString(kultura));
0
WeiXiao napisał(a):

CultureInfo.CurrentCulture – używamy gdy chcemy sformatować dane od użytkownika na przykład z formularzy itd. Odczytywanie CurrentCulture nie zawsze jest prawdziwe i trzeba na to zwrócić uwagę.

Doprecyzowujac, dla aplikacji serwerowych (asp.net) trzeba uwazac bo CurrentCulture to bedzie kultura ustawiona na serwerze a nie na komputerze uzytkownika.

1
Juhas napisał(a):

Cześć, sprawdziłem CultureInfo.CurrentUICulture.NumberFormat i WSZYSTKIE decimalseparatory mam ustawione na przecinek.

Trzeba było sprawdzić NumberFormatInfo.CurrentInfo, bo float.TryParse korzysta z CurrentCulture, a nie CurrentUICulture.

0

W czym jest problem ?
Co komu jeszcze nie działa ?

0
somekind napisał(a):
Juhas napisał(a):

Cześć, sprawdziłem CultureInfo.CurrentUICulture.NumberFormat i WSZYSTKIE decimalseparatory mam ustawione na przecinek.

Trzeba było sprawdzić NumberFormatInfo.CurrentInfo, bo float.TryParse korzysta z CurrentCulture, a nie CurrentUICulture.

Sprawdzę to. Niemniej jednak jest to trochę głupie. Użytkownik wpisuje dane z przecinkiem (UI), a powinien z kropką :|

0

Nie no, na polskich ustawieniach powinien z przecinkiem. Jeśli to nie działa, to znaczy, że albo ma inny język w systemie albo w aplikacji jest podmieniona kultura dla wątku.

0

Właśnie o to chodzi, że nigdzie nie podmieniam kultury, lecę na Current(UI)Culture. Język w systemie (Win10) jest ustawiony na polski, chociaż faktycznie czasem wkrada się coś angielskiego. Np. na ekranie powitalnym data przez chwilę jest po polsku, a potem zmienia się na angielski. Ale tak było od nowości. Natomiast bardzo niepokoi mnie ten Culture. Bo z założenia, apka ma działać na różnych ustawieniach językowych i teraz po prawdzie nie wiem za bardzo na co mam zwrócić uwagę, gdy się dzieją takie cyrki.

0

Nawet jak masz ustawioną kulturę na pl-PL to też możesz mieć kropkę , przecinek albo nawet gwiazdkę . Zależy co wpiszesz w ustawienia w Windowsie
Napisałem wszystko a wy macie nadal problem

0
Juhas napisał(a):

Właśnie o to chodzi, że nigdzie nie podmieniam kultury, lecę na Current(UI)Culture. Język w systemie (Win10) jest ustawiony na polski, chociaż faktycznie czasem wkrada się coś angielskiego. Np. na ekranie powitalnym data przez chwilę jest po polsku, a potem zmienia się na angielski. Ale tak było od nowości. Natomiast bardzo niepokoi mnie ten Culture. Bo z założenia, apka ma działać na różnych ustawieniach językowych i teraz po prawdzie nie wiem za bardzo na co mam zwrócić uwagę, gdy się dzieją takie cyrki.

A jakby wymusić "," i nałożyć jakiś input mask który nie pozwala użyć .? (lub odwrotnie) :D

0

Sprawdzałeś ustawienia w Windowsie ?

0

Przecież ja wszystko napisałem wcześniej gdzie się ustawia w Windowsie i jak się podmienia symbol dziesiętny w metodzie Parse i w stringu !
To co ja piszę jest niewidoczne ?

0
Juhas napisał(a):

Właśnie o to chodzi, że nigdzie nie podmieniam kultury, lecę na Current(UI)Culture. Język w systemie (Win10) jest ustawiony na polski, chociaż faktycznie czasem wkrada się coś angielskiego. Np. na ekranie powitalnym data przez chwilę jest po polsku, a potem zmienia się na angielski.

No i potem ten angielski zostaje, czyż nie? To by wyjaśniało problem. W Windows 10 możesz mieć inny język na ekranie logowania i inny w systemie.

Natomiast bardzo niepokoi mnie ten Culture. Bo z założenia, apka ma działać na różnych ustawieniach językowych i teraz po prawdzie nie wiem za bardzo na co mam zwrócić uwagę, gdy się dzieją takie cyrki.

Są dwa wyjaśnienia - albo Windows jest zepsuty, albo tak naprawdę masz ustawiony inny język. Strzelam, że to drugie.

Zakręcony Kret napisał(a):

Nawet jak masz ustawioną kulturę na pl-PL to też możesz mieć kropkę , przecinek albo nawet gwiazdkę . Zależy co wpiszesz w ustawienia w Windowsie
Napisałem wszystko a wy macie nadal problem

Ty masz problem z czytaniem ze zrozumieniem. Twoja porada po pierwsze nie ma związku z problemem - bo nikt nie ma zamiaru zmieniać domyślnych ustawień regionalnych, a po drugie dotyczyła innego systemu operacyjnego.
I przestań pisać z anonima, skoro masz tu konto.

0

Będziesz później tłumaczył klientowi, że ma złe ustawienia w systemie?
Po to używam odpowiednich właściwości (np. CurrencyDelimiter), żeby odpowiednio sformatować to, co gościu wpisuje do textBoxa. Ale CurrencyDelimiter swoje, a TryParse swoje.

0

@Juhas - no ale to przecież nie wina programisty, jeśli ktoś pisze w innym języku niż ma skonfigurowany w systemie.
Alternatywnie możesz wymusić jeden format, ale to będzie niewygodne dla 99% użytkowników. No chyba, że celujesz tylko w jeden kraj.

0

No, ale zaraz. Po to są chyba te pola (CurrencyDecimalSeparator itd), żeby właśnie nie dopuścić do takiej sytuacji, tak?
Teraz robię tak:

  • pobieram sobie DecimalSeparator
  • zamieniam w inpucie (podanym przez usera) kropkę na DecimalSeparator
  • zamieniam w inpucie przecinek na DecimalSeparator

Dzięki temu mam pewność, że mam poprawnie sformatowany input. Natomiast TryParse jest innego zdania. Zupełnie jakby nie brał pod uwagę DecimalSeparator, tylko zupełnie coś innego. Tak, jak pisałeś wcześniej, sprawdzę jeszcze CurrentCulture zamiast CurrentUICulture.
Więc uważam, że skoro biorę pod uwagę DecimalSeparatory z aktualnej kultury, to jestem zgodny z ustawieniami systemowymi. Czy nie jest tak?

0
Juhas napisał(a):

No, ale zaraz. Po to są chyba te pola (CurrencyDecimalSeparator itd), żeby właśnie nie dopuścić do takiej sytuacji, tak?
Teraz robię tak:

  • pobieram sobie DecimalSeparator
  • zamieniam w inpucie (podanym przez usera) kropkę na DecimalSeparator
  • zamieniam w inpucie przecinek na DecimalSeparator

To Ty zamiast po prostu sparsować robisz najpierw jakieś operacje na tym tekście? W ten sposób z liczby wychodzi coś, co niekoniecznie jest tym, co podał użytkownik, więc nic dziwnego, że nie działa.

0

Zawsze jest też bezpieczniejsza? opcja - rozbić to na 2 inputy

Aktualnie:

Koszt: [12,55] / [12.55]

Rozbite:

Koszt: [12] zł [55] gr. / [12],[55]

A później samemu sobie to jakoś zamienić pod spodem

Chociaż tobie raczej nie chodzi o kwoty, więc nie zawsze to będzie intuicyjne dla usera rozwiązanie i może gorzej wyglądać na UI.

1

Pro hint: Niektóre liczby mają więcej niż 2 cyfry. Niektóre nawet więcej niż 3, a wtedy zazwyczaj występuje coś takiego jak separator grupy. I jeśli w jakiejś kulturze separator grupy pokrywa się z tym, co próbujemy wymusić jako separator dziesiętny, to wychodzi śmiesznie.

0

Ja jedyne, co robię, to dopuszczam TYLKO wprowadzanie cyfr, przecinka i kropki do TextBoxa.
Następnie zamieniam przecinek i kropkę na DecimalSeparator odczytany z CurrentUICulture.
Na koniec parsuje.

1
Juhas napisał(a):

Ja jedyne, co robię, to dopuszczam TYLKO wprowadzanie cyfr, przecinka i kropki do TextBoxa.
Następnie zamieniam przecinek i kropkę na DecimalSeparator odczytany z CurrentUICulture.
Na koniec parsuje.

A co jeśli DecimalSeparator nie jest ani kropką ani przecinkiem? Masz buga.

0
Juhas napisał(a):

Ja jedyne, co robię, to dopuszczam TYLKO wprowadzanie cyfr, przecinka i kropki do TextBoxa.
Następnie zamieniam przecinek i kropkę na DecimalSeparator odczytany z CurrentUICulture.
Na koniec parsuje.

Ale po co? Tak możesz tylko zepsuć. Np. jeśli ktoś wprowadzi liczbę w formacie brytyjskim: 123,456.78 albo hiszpańskim 123.456,78, to po takim przetworzeniu wyjdzie mu na pewno nie liczba, którą podał.
A w ogóle to najprościej nie używać TextBoxa tylko jakiejś kontrolki do pobierania liczb, np. NumericUpDown.

0

Metoda Parse domyślnie uważa za separator dziesiętny znak , który jest ustawiony w Windowsie . Jeśli nie chcesz zmieniać ustawień Windowsa to możesz wymusić
w programie konkretną kulturę i znak separatora dziesiętnego . W metodzie ToString wywołanej niejawnie lub jawnie domyślnie jest separator z Windowsa i też możesz go zmienić.
Jeśli użytkownik użyje kropki zamiast przecina to zgłaszasz komunikat nieprawidłowy format liczby i do widzenia. Ja nie widzę żadnego problemu

0

Jeśli chcesz zachować bieżącą kulturę ale żeby separatorem była zawsze kropka to możesz napisać tak:

 string s = "12.55";
            float f;
            CultureInfo kultura = new CultureInfo(CultureInfo.CurrentCulture.Name);
            kultura.NumberFormat.NumberDecimalSeparator = ".";
            bool b = float.TryParse(s, NumberStyles.Any, kultura, out f);
            Console.WriteLine(b + " " + f.ToString(kultura));

A jak chcesz żeby separatorem były dwie gwiazdki ** to możesz napisać tak :

string s = "12**55";
            float f;
            CultureInfo kultura = new CultureInfo(CultureInfo.CurrentCulture.Name);
            kultura.NumberFormat.NumberDecimalSeparator = "**";
            bool b = float.TryParse(s, NumberStyles.Any, kultura, out f);
            Console.WriteLine(b + " " + f.ToString(kultura));
        }

To zadziała na komputerze Polaka , Chińczyka czy Anglika

0

No dobra, czy to oznacza, że nie powinienem polegać na zastanym decimalSeparator, tylko ustawić własny na sztywno w aktualnej kulturze?

1 użytkowników online, w tym zalogowanych: 0, gości: 1