49

What is the best way to parse a float in CSharp? I know about TryParse, but what I'm particularly wondering about is dots, commas etc.

I'm having problems with my website. On my dev server, the ',' is for decimals, the '.' for separator. On the prod server though, it is the other way round. How can I best capture this?

mskfisher
  • 3,291
  • 4
  • 35
  • 48
Boris Callens
  • 90,659
  • 85
  • 207
  • 305
  • 1
    Willing to that as it seems everybody's doing it. I personally try to keep away from <3 char search terms. Think it's something that stuck with me from passed times when all searches had to be >3 chars. Also the # sign makes my spider sences tingle. – Boris Callens Sep 30 '08 at 09:00

11 Answers11

64

I agree with leppie's reply; to put that in terms of code:

string s = "123,456.789";
float f = float.Parse(s, CultureInfo.InvariantCulture);
Sam
  • 7,252
  • 16
  • 46
  • 65
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
28

Depends where the input is coming from.

If your input comes from the user, you should use the CultureInfo the user/page is using (Thread.CurrentThread.CurrentUICulture).

You can get and indication of the culture of the user, by looking at the HttpRequest.UserLanguages property. (Not correct 100%, but I've found it a very good first guess) With that information, you can set the Thread.CurrentThread.CurrentUICulture at the start of the page.

If your input comes from an internal source, you can use the InvariantCulture to parse the string.

The Parse method is somewhat easier to use, if your input is from a controlled source. That is, you have already validated the string. Parse throws a (slow) exception if its fails.

If the input is uncontrolled, (from the user, or other Internet source) the TryParse looks better to me.

GvS
  • 52,015
  • 16
  • 101
  • 139
7

If you want persist values ( numbers, date, time, etc... ) for internal purpose. Everytime use "InvariantCulture" for formating & parsing values. "InvariantCulture" is same on every computer, every OS with any user's culture/language/etc...

string strFloat = (15.789f).ToString(System.Globalization.CultureInfo.InvariantInfo);
float numFloat  = float.Parse(System.Globalization.CultureInfo.InvariantInfo, strFloat);
string strNow   = DateTime.Now.ToString(System.Globalization.CultureInfo.InvariantInfo);
DateTime now    = DateTime.Parse(System.Globalization.CultureInfo.InvariantInfo, strNow);
AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
TcKs
  • 25,849
  • 11
  • 66
  • 104
6

You could always use the overload of Parse which includes the culture to use?

For instance:

double number = Double.Parse("42,22", new CultureInfo("nl-NL").NumberFormat); // dutch number formatting

If you have control over all your data, you should use "CultureInfo.InvariantCulture" in all of your code.

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
Davy Landman
  • 15,109
  • 6
  • 49
  • 73
4

Use a neutral culture (or one you know) when parsing with Try/Parse.

leppie
  • 115,091
  • 17
  • 196
  • 297
1

Pass in a CultureInfo or NumberFormatInfo that represents the culture you want to parse the float as; this controls what characters are used for decimals, group separators, etc.

For example to ensure that the '.' character was treated as the decimal indicator you could pass in CultureInfo.InvariantCulture (this one is typically very useful in server applications where you tend to want things to be the same irrespective of the environment's culture).

Greg Beech
  • 133,383
  • 43
  • 204
  • 250
0

Try to avoid float.Parse, use TryParse instead as it performs a lot better but does the same job. this also applies to double, DateTime, etc...

(some types also offer TryParseExact which also performs even better!)

Joachim Kerschbaumer
  • 9,695
  • 7
  • 49
  • 84
  • 1
    Does TryParse really work faster even when all the data is valid? I would expect them to have the same performance in the "success" case, but for failure to be faster with TryParse than Parse due to the cost of throwing exceptions. – Jon Skeet Sep 29 '08 at 15:48
  • And then again, what if TryParse returns false -- are you going to throw an exception? In that case float.Parse is more efficient than TryParse! – Sklivvz Sep 30 '08 at 08:32
  • if the strings you parse are mostly valid floats, tryparse is definitely faster. if you have lots of different strings maybe parse is the better choice, but when getting lots of strings (dozens of thousands) that are all (in 99% of the cases) valid floats in string representation, use tryparse. – Joachim Kerschbaumer Oct 17 '08 at 12:43
  • 1
    Are you sure you don't mean the other way round? I would guesstimate that Parse is only usefull with lots of correct floats and TryParse has some overhead that pays only when there is a larger chance the string is invalid.. – Boris Callens Dec 23 '08 at 12:38
0

The source is an input from a website. I can't rely on it being valid. So I went with TryParse as mentioned before. But I can't figure out how to give the currentCulture to it.

Also, this would give me the culture of the server it's currently running on, but since it's the world wide web, the user can be from anywhere...

Boris Callens
  • 90,659
  • 85
  • 207
  • 305
0

you can know current Cuklture of your server with a simple statement:

System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture;

Note that there id a CurrentUICulture property, but UICulture is used from ResourceMeanager form multilanguages applications. for number formatting, you must considere CurrentCulture.

I hope this will help you

Abdel Raoof Olakara
  • 19,223
  • 11
  • 88
  • 133
stefano m
  • 4,094
  • 5
  • 28
  • 27
0

One approach is to force localization to use dot instead of comma separator - this way your code will work identically on all windows machines independently from selected language and settings.

This approach is applicable to small gained applications, like test applications, console applications and so on. For application, which was localization in use this is not so useful, but depends on requirements of application.

var CurrentCultureInfo = new CultureInfo("en", false);
CurrentCultureInfo.NumberFormat.NumberDecimalSeparator = ".";
CurrentCultureInfo.NumberFormat.CurrencyDecimalSeparator = ".";
Thread.CurrentThread.CurrentUICulture = CurrentCultureInfo;
Thread.CurrentThread.CurrentCulture = CurrentCultureInfo;
CultureInfo.DefaultThreadCurrentCulture = CurrentCultureInfo;

This code forces to use dot ('.') instead of comma, needs to be placed at application startup.

TarmoPikaro
  • 4,723
  • 2
  • 50
  • 62
-1

Since you don't know the web user's culture, you can do some guesswork. TryParse with a culture that uses , for separators and . for decimal, AND TryParse with a culture that uses . for separators and , for decimal. If they both succeed but yield different answers then you'll have to ask the user which they intended. Otherwise you can proceed normally, given your two equal results or one usable result or no usable result.

Windows programmer
  • 7,871
  • 1
  • 22
  • 23
  • If you are going to mark down the accepted answer at least explain why you are marking it down... – Omar Kooheji Oct 02 '08 at 16:20
  • This answer was marked down before being accepted. Actually I'm a bit surprised to see this was accepted, since someone else suggested looking at the HttpRequest.UserLanguages property. I think my answer should be in second place though. – Windows programmer Oct 02 '08 at 23:43
  • Oh, now it's been marked down a second time after being accepted. I agree with that suggestion now, whoever marked it down after acceptance should at least explain why. – Windows programmer Oct 03 '08 at 05:33