This is my code:
string myValue = "0,203";
decimal.TryParse(myValue, NumberStyles.Any, CultureInfo.CurrentCulture, out myValueAsDecimal;
...
myValueAsDecimal is 0.203 now
Is it possible that myValueAsDecimal has 0,203 after TryParse or the internal representation of decimal is always 0.203 and I need to format GUI output if I need 0,203?
Is it possible that myValueAsDecimal has 0,203 after TryParse
No. It's just a number - it has no concept of a text format. To think about it another way with a simpler type, consider these two lines of code:
int x = 0x100;
int y = 256;
Are those two values the same? Yes, they represent the same number. If you convert the values of x and y to strings, by default they will both end up as "256" - but they could both end up as "100" if you request a hex representation.
It's important to distinguish between the real value of a variable and a textual representation. Very few types (none that I can think of immediately) carry around information about a textual representation with them - so for example, a DateTime can be parsed from a variety of formats, but has no "memory" of an original text format. It's just a date and time, which could then be formatted according to any format.
If you need to maintain the idea of "a decimal number and the culture in which it was originally represented" then you should create your own class or struct for that pairing. It's not present in decimal itself.
decimal d = 0.203m;
Console.WriteLine(d.ToString(CultureInfo.InstalledUICulture));
Console.WriteLine(d.ToString(CultureInfo.InvariantCulture)); // decimal point: dot
Console.WriteLine(d.ToString(CultureInfo.GetCultureInfo("en-US"))); // default decimal point: dot
Console.WriteLine(d.ToString(CultureInfo.GetCultureInfo("ru-RU"))); // default decimal point: comma
Result:
0,203
0.203
0.203
0,203
Looks like your CurrentCulture has , as a NumberDecimalSeparator and that's why your parsing succeed.
Actually, 0.203 and 0,203 are the same as value. Only matter is their textual representation when you print it.
If you wanna get your value as a 0,203 representation, you can use a culture that has , as a NumberDecimalSeparator.
For example, my culture (tr-TR) has a ,. When you represent your decimal with it, you will get 0,203.
string myValue = "0,203";
decimal myValueAsDecimal;
decimal.TryParse(myValue, NumberStyles.Any, CultureInfo.CurrentCulture, out myValueAsDecimal);
myValueAsDecimal.ToString(new CultureInfo("tr-TR")).Dump(); // 0,203
The value of the Decimal is the same regardless of the Culture, it's
0.203
what changes is its String representation (decimal separator in your case), so
if you want to change decimal separator and don't want to change the Culture
you can just assign NumberDecimalSeparator in your custom NumberFormatInfo e.g.
Decimal d = 0.203M;
NumberFormatInfo myNumberInfo = new NumberFormatInfo() {
NumberDecimalSeparator = "," // Comma, please
};
String result = d.ToString(myNumberInfo); // "0,203"
Related
I have a string that contains: 2.53 and I'm trying to convert this number into decimal type, so I did:
string value = "2.53";
decimal converted = Convert.ToDecimal(value);
but the final result is: 253
Decimal point is different in every culture. In your culture it might be a comma. You can use InvariantCulture which has dot as decimal separator:
decimal converted = Convert.ToDecimal(value, CultureInfo.InvariantCulture);
I have a double value as below
double propertyValue = 1994.7755474452554;
When i convert this double value to a string
string value = propertyValue.ToString();
it gives the value "1994.77554744526"
It has rounded off the last digits 2554 to 26.
But I do not want to round the value. Share your ideas.
By default the .ToString() method of Double returns 15 digits of precision. If you want the full 17 digits that the double value holds internally, you need to pass the "G17" format specifier to the method.
String s = value.ToString("G17");
This will prevent the rounding off of double value when converted to string.
value = propertyValue.ToString("G17");
You could use decimal type instead.
decimal propertyValue = 1994.7755474452554M;
I can't reproduce the misbehaviour; you've experienced a representation effect: it's ToString() puts double like that.
string source = "1994.7755474452554";
double d = double.Parse(source, CultureInfo.InvariantCulture);
string test = d.ToString("R", CultureInfo.InvariantCulture);
Console.Write(source.Equals(test) ? "OK" : "Rounded !!!");
Outcome is OK. Please, notice "R" format string:
The Round-trip ("R") Format Specifier
https://msdn.microsoft.com/en-us/library/dwhawy9k(v=vs.110).aspx#RFormatString
You can cast double to decimal and use the default ToString() like this:
Double propertyValue = 1994.77554744526;
var str = ((decimal)propertyValue).ToString();
//str will hold 1994.77554744526
I want to convert a string into int. I have string value like this "45,454,566.00". While typecasting throwing error
Input string was not in a correct format
int GrandTotalInWords = Int32.Parse(grandtotal);//error
grandTotalInWords.InnerHtml = ConvertNumbertoWords(GrandTotalInWords);
First of all, int.Parse uses NumberStyles.Integer which does not includes any thousands and decimal separator styles.
As a second, your CurrentCulture might not use , as a NumberGroupSeparator and/or might not use . as a NumberDecimalSeparator.
Just specify your culture settings and number styles;
int GrandTotalInWords = int.Parse(grandtotal,
NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands,
CultureInfo.InvariantCulture);
By the way, if your fraction part is not always zero, that makes your string is not a valid format for an int. In such a case, you might need to parse it to a floating-point type like double as;
double GrandTotalInWords = double.Parse(grandtotal,
NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands,
CultureInfo.InvariantCulture);
I have tried:
MessageBox.Show(System.Numerics.BigInteger.Parse("7.56e+011",
NumberStyles.Float,
CultureInfo.InvariantCulture));
But it continues to show 7.56e+011
You are looking to format the number. You can use String.Format to do so
string.Format("{0:F}",System.Numerics.BigInteger.Parse("7.56e+011",
NumberStyles.Float,
CultureInfo.InvariantCulture))
Running the following code
Gives you the following MessageBox
you can specify no decimal points by changing it to {0:F0} for the format.
Try
BigInteger num = System.Numerics.BigInteger.Parse("7.56e+011",
NumberStyles.Float,
CultureInfo.InvariantCulture);
String text = num.ToString("F5"); // New format string, here with 5 digits.
Your solution does an implicit conversion from BigInteger back to string again, which uses the scientific notation if the exponent is large.
decimal dec = decimal.Parse("7.7583877127496407E-6",
System.Globalization.NumberStyles.Any);
Console.WriteLine(dec);
Situation - The thread culture in my web app has been set to 'es' (Spanish)
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture("es");
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("es");
The string value is "0.1"
For the following expression,
var value = "0.1"
provider = CultureInfo.CreateSpecificCulture("en-US")
double.TryParse(value.ToString(), NumberStyles.Any, provider, out number)
number returns 1.0. Which makes me think that it is picking the culture info from the thread. Not the one I provide.
The following unit test passes (as expected).
var numberInEnUS = "0.1";
var spanishCulture = CultureInfo.CreateSpecificCulture("es");
culture = new CultureInfo("en-US", false);
Thread.CurrentThread.CurrentCulture = spanishCulture;
Thread.CurrentThread.CurrentUICulture = spanishCulture;
double number;
double.TryParse(numberInEnUs, NumberStyles.Any, culture, out number);
Assert.AreEqual(0.1, number);
So, the question is why does double.TryParse fail in my application? Theoretically, 0.1 for Spanish is 1 (Separator for spanish is a decimal point '.'). However, number 1000.0 does not get converted to 10000. So, it seems that it fails only for 0.1
Any explanation is highly appreciated!
You say "0.1" is number in spanish. Actually not, It is numberInEnglish or something else
var numberInSpanish = "0.1";//this is number in english culture
It should be
var numberInSpanish = "0,1";//<--Note 0,1
NumberDecimalSeparator for spanish is ,. Parse 0,1 you'll get expected result.
var numberInSpanish = "0,1";
var spanishCulture = CultureInfo.CreateSpecificCulture("es");
var culture = new CultureInfo("en-US", false);
Thread.CurrentThread.CurrentCulture = spanishCulture;
Thread.CurrentThread.CurrentUICulture = spanishCulture;
double number;
double.TryParse(numberInSpanish, NumberStyles.Any, spanishCulture, out number);
Here number is correctly parsed to "0.1"
Your problem is in the mixture of decimal and thousand separators, namely:
'.' - thousand separator in "es" culture, when parsing, will be ignored (e.g. 1.000,0 == 1000,0)
',' - decimal deparator in "es" culture, separates integer and fractional parts
You can easily convince yourself:
var spanishCulture = CultureInfo.CreateSpecificCulture("es");
Char dS = spanishCulture.NumberFormat.NumberDecimalSeparator; // <- ','
Char tS = spanishCulture.NumberFormat.NumberGroupSeparator; // <- '.'
So, in your case the string "0.1" will be converted into 1.0 double since '.' as
being a thousand separator in es culture will be ignored.
You can do either:
Use Invariant culture instead of "es" one:
double.TryParse(numberInNeutral, NumberStyles.Any, CultureInfo.InvariantCulture, out number);
Or use actual Spanish number representation:
var numberInSpanish = "0,1";
double.TryParse(numberInSpanish, NumberStyles.Any, culture, out number);
I finally was able to identify what was wrong. The issue was not with the TryParse() function but the ToString() function.
The value was actually a Double type, not a string as I mentioned above. (My bad, I thought it was not relevant). I was actually doing a value.ToString(). This is where it uses the thread culture and changes the value.
So, if the value was 0.1, the value.ToString() changes it to "0,1". It automatically changes the decimal character based on the Thread culture. The TryParse then uses the en-US culture and convert "0,1" to 1.
To fix it, use Convert.ToString instead and pass in the culture info.
At the end, it was just a silly mistake.
LessonLearnt - Be careful when using ToString() in globalized applications!