I know this is the silliest question to ask. But really I'm having trouble to convert price(string) to decimal. Here is what I have tried
string s = "123.45";
decimal d = decimal.Parse(s, NumberStyles.AllowCurrencySymbol | NumberStyles.AllowThousands | NumberStyles.AllowDecimalPoint);
But I'm getting Format exception
Also tried
decimal num;
bool pass = decimal.TryParse("2.85", out num);
num comes out as 0.
Any help will be greatly appreciated.
Try specifying an invariant culture in which . is the decimal separator:
string s = "123.45";
decimal d = decimal.Parse(
s,
NumberStyles.AllowCurrencySymbol | NumberStyles.AllowThousands | NumberStyles.AllowDecimalPoint,
CultureInfo.InvariantCulture
);
The Parse method uses the current thread culture to parse numbers. So if you are using some culture in which . is not the decimal separator (such as fr-FR for example) it won't work as it would expect the number to be 123,45 for instance.
Related
I'm new to c# and tried to convert the input into decimal and double. It works fine when I enter an intiger but stops immediately when I enter a decimal or double number and gives me an "Exception Unhandeled" Error message.
My code:
Console.Write("Enter number: ");
decimal d = Convert.ToDecimal(Console.ReadLine());
Console.WriteLine(d);
So when I enter 3 the program prints out the number 3. But if I enter 3.6, it stops.
I've seen another solution using Double.Parse(); but still can't make my code work.
Console.Write("Enter number: ");
decimal d = Decimal.Parse(Console.ReadLine());
Console.WriteLine(d);
In my codes I'm using decimal but the same applies to double.
I've tried to look up other questions like this (stackoveflow, google), I've checked out the documentation but couldn't find the issue.
What's wrong with my code?
All string conversion operations use the current culture, which may differ in things like decimal or thousands separator and other things. You can specify the invariant culture in any of these conversions:
decimal d = Convert.ToDecimal(Console.ReadLine(), CultureInfo.InvariantCulture);
decimal d = Decimal.Parse(Console.ReadLine(), CultureInfo.InvariantCulture);
Another option is to set the default culture at the start of your application, which will affect all future conversions:
CultureInfo.CurrentCulture = CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
Well, if you use decimal for finance you may want to accept not only decimal separator, but group (thousand) one:
123,456,789.45
here . is a decimal separator when , are group ones. To support group separator you can specify NumberStyles.Any
Console.Write("Enter number: ");
decimal d;
while (!Decimal.TryParse(Console.ReadLine(), NumberStyles.Any, null, out d))
Console.WriteLine("Invalid syntax. Please, try again.");
Please, note that here I've put null that stands for CultureInfo.CurrentCulture which at your workstation seems has , for decimal separator and . for group one:
"123.45" -> 12345m - note, that group separator(s) is/are removed
"1.2.3.4.5" -> 12345m
"123,45" -> 123.45m - while decimal is turned into decimal point
If you want to treat . as a decimal separator (so "123.45" will be parsed into 123.45m), you can specify CultureInfo.InvariantCulture:
Console.Write("Enter number: ");
decimal d;
while (!Decimal.TryParse(Console.ReadLine(),
NumberStyles.Any,
CultureInfo.InvariantCulture,
out d))
Console.WriteLine("Invalid syntax. Please, try again.");
As was mentioned in comments, a decimal separator is varying from country to country. I would suggest to manual replace the entered symbol to the separator used in your culture:
string separator = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
decimal d = Decimal.Parse(Console.ReadLine().Replace(".", separator).Replace(",", separator));
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);
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"
i am working on a problem to round decimal values everything is fine but at one certain point it gives me error input string was not formatted after debugging my code i found 4.90702817E-05 this which gives me error on this calling code . It converts all code but throws exception when it finds above string .
MarketValue = Convert.ToDecimal(row["MarketValue"].ToString()) ,
MarketValue = Decimal.Parse(row["MarketValue"].ToString(), NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint);
Convert to Decimal by using below code. After getting the Value in Decimal form round it up.
decimal d = Decimal.Parse("4.90702817E-05", System.Globalization.NumberStyles.Float);
The reason for the exception could be that the value is not a valid decimal.
The following code uses a method called TryParse(...). This method returns false if the value is not a valid decimal, rather than throwing an exception.
For example:
decimal d = 0;
if (Decimal.TryParse(row["MarketValue"].ToString(), out d))
{
MarketValue = d;
}
I'd advise you to use TryParse using following NumberStyles
decimal d = 0;
if (Decimal.TryParse(row["MarketValue"].ToString(), NumberStyles.AllowExponent | NumberStyles.AllowDecimalPoint, CultureInfo.CurrentCulture, out d))
{
MarketValue = d;
}
I'm trying to parse values like $15,270.75 with the expression
double cost = 0;
double.TryParse("$15,270.75", NumberStyles.AllowThousands | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture, out cost);
but have no success
The currency symbol of Invariant culture is not $, its ¤. This works:
double cost = double.Parse("¤15,270.75", NumberStyles.AllowThousands | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
You'll need a CultureInfo that supports exactly this format.
The following works:
var culture = new CultureInfo("en-US");
culture.NumberFormat.CurrencyGroupSeparator = ".";
culture.NumberFormat.CurrencyDecimalSeparator = ",";
double.TryParse("$15.270,75", NumberStyles.AllowThousands | NumberStyles.AllowCurrencySymbol | NumberStyles.AllowDecimalPoint, culture, out cost);
The culture I used here is en-US for the $ symbol. The reason I manually set the group and decimal separators is because the format used in the input string are different from the culture of en-US.
Maybe you are expecting a specific culture that is not en-US. Try passing that one.
this is because you are using InvariantCulture. you need an american CultureInfo
This will not work with CultureInfo.Invariant culture. Use an appropriate CultureInfo.
If you want something that works for any locale, use CultureInfo.CurrentCulture for the IFormatProvider parameter.