Double.Parse - Internationalization problem - c#

This is driving me crazy. I have the following string in a ASP.NET 2.0 WebForm Page
string s = "0.009";
Simple enough. Now, if my culture is Spanish - which is "es-ES" - and I try to convert the string to Double, I do the following:
double d = Double.Parse(s, new CultureInfo("es-ES"));
what I'd expect is 0,009. Instead, I get 9. I understand that .NET thinks it is a thousand separator, which in en-US is a comma, but shouldn't it take the culture info I'm passing to the parse method and apply the correct format to the conversion?
If I do
double d = 0.009D;
string formatted = d.ToString(new CultureInfo("es-ES"));
formatted is now 0,009. Anybody?

It is taking the culture you gave and applying the correct formatting. You provided a string of "0.009" and told it that it was Spanish...then you complain that it properly interpreted it as Spanish! Don't tell it that the string is Spanish when you know it isn't.
You should pass the Parse method the culture of the string being parsed, which in this case would be en-US or en-Gb or InvariantCulture.

what Jess's writing works for me. just for anyone who'd need to try out how to get "invariant culture": it looks this
double d = Double.Parse(myString, CultureInfo.InvariantCulture);
(first stackoverflow post, so yea, rather marginal ;)

You have it backwards.
When you say double d = Double.Parse(s, new CultureInfo("es-ES"));, you are asking .NET to parse your string into a double, assuming that the string is written in the es-ES culture.
In Spanish culture, "." is a thousands separator, so "0.009" is 9.
When you convert using ToString(), at the end, it's saying convert 0.009 to a string using the spanish culture, so it uses "," as the decimal separator, and you get "0,009". The behavior is correct.
My guess is that you want to use Double.Parse with the Invariant Culture, and ToString with the spanish culture, so 0.009 becomes 0,009.

I think you are interpreting it the wrong way around, in es-ES culture 0.009 is really just a long way of saying 9, as the "." is not the decimal separator, so if you ask for the string "0.009" to be parsed with the es-ES culture you should indeed get the deouble 9.0. If you ask it to parse "0,009" you should get a double of 0.009.
Similarly, if you ask it to format the double 0.009 you should get the string "0,009" in es-ES.

You're mistaking parsing and formatting. You get 9 instead of .009 the first time because you take a string that is formated in a .-based culture and parse it using a ,-based culture. You need to parse it using whatever culture it was created with and then format it using whatever culture you want for display.

double d = Double.Parse("0,009",
NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands,
CultureInfo.CreateSpecificCulture("es-ES"));
In es-ES culture "," is a decimal seporator (not ".")

Related

Invariant decimal variable

Please observe following simple code. Why the variable inVarient prints without decimal point. I want decimal point, how to achieve it?
decimal actualVal = 1247315.93m;
string inSwedish = actualVal.ToString(CultureInfo.CreateSpecificCulture("sv-SE"));
decimal inVarient = decimal.Parse(inSwedish, CultureInfo.InvariantCulture);
Console.WriteLine(inSwedish); //prints 1247315,93 (as intended)
Console.WriteLine(inVarient); //prints 124731593 (I need 1247315.93)
Console.Read();
This is because you're trying to parse a string that represents a decimal formatted with the Swedish culture but you're trying to parse it with the invariant culture, which won't treat a comma as a decimal point. You need something like this:
decimal actualVal = 1247315.93m;
var culture = CultureInfo.CreateSpecificCulture("sv-SE");
string inSwedish = actualVal.ToString(culture));
decimal invariant = decimal.Parse(inSwedish, culture);
Console.WriteLine(inSwedish);
Console.WriteLine(invariant.ToString(CultureInfo.InvariantCulture));
Console.Read();
Swedish culture uses , as a decimal separator, the invariant culture uses ., so when it parses a string using the comma as a separator it just ignores it.
The reason why your decimal point disappears here is because in the invariant culture, a comma is a thousands separator, not a decimal separator. Thus, it assumes it can safely ignore commas when parsing a numeric text.
If you go back and forth from a culture to another, this kind of thing is to be expected.
I don't know what your real context is but if you want to recover the numeric as it originally was before it was made a string, you must either use consistent formatters throughout your code or not storing decimals into string variables only to parse them back to decimal again.
If there's no need to serialize anything the latter is the way to go.

String.Format an integer to use a thousands separator with decimal value in danish culture

I have a string totalPRice which holds a value like this 1147,5
I want two things.
1)round the value so that there is always two digits after ,
2)Implement thousands separator in this string, So that final out put will be some thing like this 1.147,50
I have tried some thing like this
String.Format("{0:0.00}", totalPRice)
It does my first requirement correctly by producing an output 1147,50.
But I am way behind in my second requirement. Can any one tell me how I can achieve this?
Note: In danish culture . stands for , and , stands for .
You can refer to Standard Numeric Format Strings and use
string.Format("{0:N2}", 1234.56)
You may also specify the culture manually, if danish is not your default culture:
var danishCulture = CultureInfo.CreateSpecificCulture("da-DK");
string.Format(danishCulture, "{0:N2}", 1234.56);
see MSDN Reference for CultureInfo
You should create a culture-specific CultureInfo object and use it when converting the number into a string. Also, you can set the default culture for your whole program.
Then, your code will look like this:
// create Dennmark-specific culture settings
CultureInfo danishCulture = new CultureInfo("da");
// format the number so that correct Danish decimal and group separators are used
decimal totalPrice = 1234.5m;
Console.WriteLine(totalPrice.ToString("#,###.##", danishCulture));
Note that . and , in the formatting string are specified opposit as you want. This is because they identify decimal and group separators, and are replaced with the correct culture specific-ones.
Try this:
String.Format("{0:N2}", totalPRice)
Another possibility is to use the ToString(string format) overload.
totalPRice.ToString("N2");
If this is a currency value (money!), then it's better to use the current format specifier 'C' or 'c':
string.Format("{0:C}", 1234.56)
Normally I don't write the number of decimal digits since it comes from the international configuration.
You may way to use a different colture specifier if you don't want to use the default one.
var colture = CultureInfo.CreateSpecificCulture("§§§§§");
string.Format(culture, "{0:C}", 1234.56);
where §§§§§ is the string that identifies the desired colture.
Try this for Price format. Put it under template field instead of BoundField.
<%#(decimal.Parse(Eval("YourDataField").ToString())).ToString("N2")%>

Converting string to decimal: how to handle the decimal separator in different cultures

I need to write decimal value to ms access database, but i have a problem with conversion values to decimal in different cultures. Have a values from file, which separates by commma. I try:
public decimal CSingleCulture (string str)
{
string sep = System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
string s = str.Replace(",", sep);
return decimal.Parse(s);
}
if NumberDecimalSeparator = "." then work is good, but if NumberDecimalSeparator = "," problems begin... decimal.Parse(s) always return vlaues separates by dot. In this situation, when inserted into a database error occurs.
The recommended way to deal with this is to store the value as a number rather than a string. Both in the database and in your program. When you do that, your current problem simply never arises.
The only time you deal with numbers in string format is when you display them, or accept user input. In those scenarios you can use the user's culture settings to let them see and use their preferred separator.
Should you ever need to convert between string and number for persistence then you must use culture invariant conversion. This appears to be where you are falling down. I suspect that the file you read has no well-defined format. Make sure that when you read and write the file you use CultureInfo.InvariantCulture. If the file does have a well-defined format that differs from the invariant culture, then use an appropriate specific CultureInfo.
Can't actually understand what is it you're trying to accomplish, and I have to agree with the other answer. But one other thing that's good to know is you can use invariant culture like so:
double.Parse("15.0", CultureInfo.InvariantCulture)
This will always expect dot character to delimit your decimal digits regardless of what is set in current thread's culture.

Language invariant Double.ToString()

I am passing a double across a network,
currently I do
double value = 0.25;
string networkMsg = "command " + value;
the networkMsg is fine in english where its 0.25 and french where its 0,25, but when i go from a french computer to an english computer one side is making it 0.25 and the other is trying to read 0,25.
So i can to use region invariant methods in my code.
I have found Val(networkMsg) that will always read 0.25 no matter the region.
but I cannot find a guaranteed way of converting from value to 0.25 region invariant.
would value.toString("0.0") work?
Use:
string networkMsg = "command " + value.ToString(CultureInfo.InvariantCulture);
or:
string networkMsg = string.Format(CultureInfo.InvariantCulture, "command {0}", value);
This needs using System.Globalization; in the top of your file.
Note: If you need full precision, so that you can restore the exact double again, use the Format solution with the roundtrip format {0:R}, instead of just {0}. You can use other format strings, for example {0:N4} will insert thousands separators and round to four dicimals (four digits after the decimal point).
Since C# 6.0 (2015), you can now use:
string networkMsg = FormattableString.Invariant($"command {value}");
The . in the format specifier "0.0" doesn't actually mean "dot" - it means "decimal separator" - which is , in France and several other European cultures. You probably want:
value.ToString(CultureInfo.InvariantCulture)
or
value.ToString("0.0", CultureInfo.InvariantCulture)
For info, you can see this (and many other things) by inspecting the fr culture:
var decimalSeparator = CultureInfo.GetCultureInfo("fr")
.NumberFormat.NumberDecimalSeparator;
Specify the invariant culture as the format provider:
value.ToString(CultureInfo.InvariantCulture);

System.Convert.ToSingle(value) always throws FormatException

I have several strings that I need to convert to float. When I try to do so, using System.Convert.ToSingle(MyString), I always get a FormatException.
I have tried even creating strings like "12.123", to make sure the numbers are okay, but again I got the exception. My question is, what is the correct format then? In what format should the number in string be?
Example of one of many strings I will convert: 50.105128
It could be down to your system's culture which may be set to using a , as the separator. Setting the format to InvariantCulture will use a . for the separator.
Convert.ToSingle("12.123", CultureInfo.InvariantCulture)
It depends on culture, but you can use invariant in this way:
Convert.ToSingle("0", System.Globalization.CultureInfo.InvariantCulture);
Convert.ToSingle is culture-sensitive. In culture installed on your machine, decimal separator might be different from comma, and number may look like 50,105128
Use this overload instead, which allows to specify culture:
public static float ToSingle(
Object value,
IFormatProvider provider
)

Categories