Decimal.TryParse - missing separator? - c#

I have strange situation, when I use API. I get object in JSON, which I deserialize. This object contains string property which is parsed to decimal.
To do this I use this code. I live in Poland where decimal separator is ',', so I use replace method.
string input ="160.00"; //value from API
decimal result;
decimal.TryParse(input.Replace('.',','), out result);
From time to time I result is equals 16000!! (I suppose TryParse method delete separator, it not determined).
How can I prevent this situation? Can I parse

Numbers should be serialized as InvariantCulture anyway so the InvariantCulture for parsing is a good start. The code serializing the numbers should also be checked whether it follows this rule.
string input ="160.00";
decimal result = decimal.Parse(
input,
System.Globalization.CultureInfo.InvariantCulture);
Not serializing numbers as culture invariant is one of the most common source of problems like it runs on my machine I have no idea why it doesn't on yours... oh you say your system is in a different language oops ;-)

Instead of replacing decimal point character you should be using a proper overload of TryParse method, i.e. decimal.TryParse(String, NumberStyles, IFormatProvider, Decimal):
string input ="160.00";
NumberStyles style = NumberStyles.Number;
decimal number = 0;
CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
decimal.TryParse(input, style, culture, out number)
Make sure to specify the correct culture which is suitable for your case.

Related

Float.Parse() ignoring decimal comma

I am getting some percent values from a database and I need to format them to have the correct thousands seperator, number of decimal places and a percent sign on the end.
I tried this:
string text = "105,3"; //example, formatting like database input
string format = "#,##0.##";
e.Row.Cells[i].Text = double.Parse(text).ToString(format);
Weirdly this returns 1053,00%. How do I make it so it returns 105,30%? (The decimal comma is because the system locale is german, so it's how it is supposed to be)
edit: replacing the comma with a period results in 10530.00%. Nothing makes sense to me anymore.
edit2: the float.Parse() actually works just fine. the ToString() messes everything up. I played around with using different cultural settings and format strings (switching comma and period) but it only makes it worse again.
Pass the current Culture to the Parse method: double.Parse( text, CultureInfo.CurrentCulture )
However, this only works on systems that use a locale that has the comma as a decimal separator.
If you want this to work on other locales you should replace CurrentCulture with the specific CultureInfo instance that used when inputting data in the first place.
The title is misleading. The actual problem was the ToString() function. In the format string I added the % sign, which, to be fair, I didn't add in the original post because I forgot about it. It automatically multiplies the number by 100. So my format string is now "#,##0.00\%".

Convert object to single. CultureInfo problems

So I have the following line of code :
Single xFreq = Convert.ToSingle(param, CultureInfo.InvariantCulture);
Variable param is a System.Object Any reason the result is not the same if the "," separator is used instead of the "."? For example 0.45 is converted correctly but 0,45 is converted to 45... This thing keeps bugging me for the last hour...
Not sure what your question is since you explicitly specifying InvariantCulture for parsing the string value - hence "." is used as separator.
You need to specify CultureInfo that matches your input. Generally to parse user input you need to use current culture. If input comes from some other source you have to know what culture it was serialized with.
Because the decimal separator is Culture dependent, as other posts clarified, for InvariantCulture it's "." (CultureInfo.InvariantCulture.NumberFormat). You can look at the NumberFormatInfo article for more details regarding other separators for number types.
Invariant culture converts from and to "." like a separator. Instead the string you converting from is not in in ariant culture format, hou need specify string's culture.
Thd basic technique in this case could be to STORE in invariant culture, but show to user what he wants like a separator, so you will get rid of any culture dependent problem and user will happy to see what he likes to see.
Regards.

C# parsing float from string

I'm reading numbers from XML files. Other numbers are with a comma separator (0,1111) and others with dot (0.1111). How do I parse these numbers so I get the desired result in the end? I tried using float.Parse(reader.Value, System.Globalization.CultureInfo.InvariantCulture); but it doesn't work. For example I have reader.Value = "0,01119703" and is parsed as 1119703.0.
I don't believe that it is possible to work with two different decimal separators at the same time. I think I would just use Replace() to change any commas into dots.
float.Parse(reader.Value.Replace(',', '.'), System.Globalization.CultureInfo.InvariantCulture);
Not sure this is the greatest solution, but perhaps you could rely on a set of known "Custom" number formats. For instance, you could declare two custom number formats (either from scratch or based off of a known format) such as:
private static readonly NumberFormatInfo DecimalSeparatorFormat = new NumberFormatInfo { NumberDecimalSeparator = ".", NumberGroupSeparator = "," };
private static readonly NumberFormatInfo CommaSeparatorFormat = new NumberFormatInfo { NumberDecimalSeparator = ",", NumberGroupSeparator = "." };
And then try parsing the number through your known accepted formats:
if (!Single.TryParse(unparsedValue, NumberStyles.Float, DecimalSeparatorFormat, out parsedValue) && !Single.TryParse(unparsedValue, NumberStyles.Float, CommaSeparatorFormat, out parsedValue))
throw new FormatException("Number format not supported");
This assumes that you have a finite number of known formats, if your inputs can truly be in any culture, then you may be out of luck with finding a great solution.
The one win with this approach is you are at least being explicit in the formats you are able to support rather than relying on a simple string replace (which may result in an invalid format).
Is there anything in the XML files that will tell you which format is being used? There's not a built-in way in .NET to have two different allowed decimal separators. If there's nothing telling you which format a number is going to be in, then you could always check to see whether the string contains a period or a comma, and create a NumberFormatInfo with that as the decimal separator. Of course, this won't work if any of the numbers have a period or comma as a thousands separator.

Convert localized string into decimal

I have a string, that could look like "123,34", "123123,09", "1234", "123.34", "123123.09"
(Stringrepresentation of 10,2 decimal that will be stored into a MySql DB)
Due to the culture of the ASP.net thread may differ, because my application supports localization, I need to find a safe way to convert the most likely user input into a decimal.
How is that possible?
I tried various Decimal.Parse attemps, that all failed so far.
Solution:
My final solution was a mixed one. I used string replace to ensure my date is formatted into the specified CultureInfo I used for parsing
You should read current Culture Info
and than you could
//CultureInfo culture = new CultureInfo("en-US");
Convert.ToDecimal(value, System.Globalization.CultureInfo.CurrentCulture)
Decimal.Parse is the way to go but you need the particular overload that incorporates localisation, Decimal.Parse Method (String, IFormatProvider).
Once the decimal is turned into a string, there is really no foolproof way of telling which culture formatting was used to format it.
You have two options :
Record the formatting culture used and pass that back with the string, then use that for the appropriate decimal.Parse(string, IFormatProvider)
Perform the parse at the UI level (where the culture is known) and pass the value back as a decimal type.
Decimal.Parse (String, IFormatProvider)
where IFormatProvider is culture-specific format for your strings
Convert your string with the InvariantCulture
Decimal.parse(yourstring,System.Globalization.CultureInfo.InvariantCulture);
Thought you might get some weird results if your string is not compatible with the cultureinfo of the system.

How to insert a thousand separator (comma) with convert to double

I am trying to format the contents of a text box:
this.lblSearchResults1.Text =
Convert.ToDouble(lblSearchResults1.Text).ToString();
How do I amend this so that I the text includes comma/thousand separators?
i.e. 1,000 instead of 1000.
Looking at the standard numeric format strings:
You can most easily use 'N' which will do the right thing based on the user culture, so in your case you can just add "N" as a param to the ToString
([double]12345.67).ToString("N")
12,345.67
For complete custom control, use ... .ToString("#,##0.00") or variations thereof. The . and , will be replaced by culture dependent symbols. In most of europe you'd get 1.234,56.
Another useful picture is 0.0#.
To use a pattern depending on the users (or on a selected) culture, use The Numeric ("N") Format Specifier, as in .ToString("N") or "... {0:N}".
The easiest way to do it would be something like:
Convert.ToDouble("1234567.12345").ToString("N")
If you want to control the decimal places you can do something like:
Convert.ToDouble("1234567.12345").ToString("N3")
In general look at the overloads on ToString for more exciting possibilities.
If you take a closer look at Standard Numeric Format Strings you can try one of the following:
.ToString("n", CultureInfo.GetCultureInfo("en-US"))
.ToString("n", CultureInfo.GetCultureInfo("de-DE"))
.ToString("n", CultureInfo.CurrentCulture)
An alternative to the above mentioned responses would be to use
this.lblSearchResults1.Text = String.Format("{0:N}", Convert.ToDouble(lblSearchResults1.Text))
If you wanted decimal places, just enter the amount of decimal places you wish to have after the N. The following example will return the value with 2 decimal places.
this.lblSearchResults1.Text = String.Format("{0:N2}", Convert.ToDouble(lblSearchResults1.Text))
See http://msdn.microsoft.com/en-us/library/system.string.format.aspx for more information.
double.Parse(Amount).ToString("N");
Do not cast integral to double to do this!
Use NumberFormatInfo helper class, e.g:
var nfi = new NumberFormatInfo() {
NumberDecimalDigits = 0,
NumberGroupSeparator = "."
};
var i = 1234567890;
var s = i.ToString("N", nfi); // "1.234.567.890"

Categories

Resources