How to convert "12,4" to decimal en-Us culture - c#

I have a decimal value ("133,3") stored in string column in the database, in norway culture.
after that user changed the regional setting to english-Us. when I convert "133,3" to decimal using CultureInfo.InvariantCulture, getting invalid value or error.
is there any best way to handle this scenario in C# application?
regards,
Anand

Regardless of the system culture, if you specify CultureInfo.InvariantCulture you won't be able to parse "133,3" as a decimal to 133.3. The same is true for US English.
You could just specify a Norwegian culture when parsing the value (using the overload of decimal.TryParse which takes an IFormatProvider), or (preferrably) change the field in the database to reflect the real data type (a decimal number) instead.

Do you referred to Convert.ToDecimal(), it says like
using System;
using System.Globalization;
public class Example
{
public static void Main()
{
string[] values = { "123456789", "12345.6789", "12 345,6789",
"123,456.789", "123 456,789", "123,456,789.0123",
"123 456 789,0123" };
CultureInfo[] cultures = { new CultureInfo("en-US"),
new CultureInfo("fr-FR") };
foreach (CultureInfo culture in cultures)
{
Console.WriteLine("String -> Decimal Conversion Using the {0} Culture",
culture.Name);
foreach (string value in values)
{
Console.Write("{0,20} -> ", value);
try {
Console.WriteLine(Convert.ToDecimal(value, culture));
}
catch (FormatException) {
Console.WriteLine("FormatException");
}
}
Console.WriteLine();
}
}
}

If you know the culture that was in use when persisting the value, you can use it when parsing it, i.e.:
Convert.ToDecimal("133,3", System.Globalization.CultureInfo.GetCultureInfo("no"));
Of course, you are probably better off changing how the data is stored in the database, to use a floating point number of some form.

Convert.ToDouble(textBox2.Text, new CultureInfo("uk-UA")).ToString(new CultureInfo("en-US"));

This solves your problem: .ToString(New CultureInfo("en-US"))

Hope it's helpful
double _number = 12536,8;
CultureInfo usCulture = new CultureInfo("en-US");
return _number.ToString("N", us);

used below code to fix my issue. I just hard coded the previous currency decimal part. may not be generic. but solved my problem.
public static decimal? ToDecimal1(this string source)
{
CultureInfo usCulture = new CultureInfo("en-US");
if (string.IsNullOrEmpty(source.Trim1()))
return null;
else
return Convert.ToDecimal(source.Replace(",", ".").Trim(), usCulture);
}

Related

Format decimal value to currency with optional precision

I have c# project. I use ToString("N", CultureInfo.CurrentCulture) for format double value and the result is like 1.254.812,45 .There is no problem. But when I have no precision I don't want to display 1.254.812,00. I want to display only 1.254.812 . How can I do it?
You can use the custom format specifier #, which only returns decimal digits if they exist in the number, both before the decimal point and after.
For example, for de-DE culture:
Console.WriteLine(1254812.45.ToString("#,###.###", CultureInfo.GetCultureInfo("de-DE")));
Console.WriteLine(1254812.0.ToString("#,###.###", CultureInfo.GetCultureInfo("de-DE")));
Output
1.254.812,45
1.254.812
dotnetfiddle
I don't know if there is a direct solution, but the Convert() method I developed provides a solution.
using System;
using System.Globalization;
public class Program
{
public static string Convert(string value)
{
if(value.Split('.')[1].Equals("00"))
return value.Split('.')[0];
return value;
}
public static void Main()
{
double[] inputs = {1254812.00, 1254812.45};
string[] results = {inputs[0].ToString("N", CultureInfo.CurrentCulture), inputs[1].ToString("N", CultureInfo.CurrentCulture)};
Console.WriteLine("{0}\t{1}", Convert(results[0]), Convert(results[1]));
}
}
This code produces the following output:
1,254,812 1,254,812.45

Strange output when converting string to double

I already searched for my problem but I wasn't successfully and that's the reason I'm here.
All I want to do is reading a string like "3.14" and convert it to double.
Enough said... here is my code:
using System;
namespace GlazerCalcApplication
{
class MainClass
{
public static void Main (string[] args)
{
string heightString;
double height;
heightString = Console.ReadLine();
height = Convert.ToDouble(heightString);
Console.WriteLine(height);
}
}
}
Output:
3.14
314
Press any key to continue...
Why is my double value not 3.14?
Instead of Convert.ToDouble() I also tried it with double.Parse() but I received the same behaviour. Reading strings like 3,14 is no problem.
Maybe I should also mention that I use MonoDevelop and a linux OS.
Thanks in advance.
Try specifying the culture as Invariant:
height = Convert.ToDouble(heightString,CultureInfo.InvariantCulture);
It seems the decimal seperator of your culture is comma instead of dot therefore dot is truncated after conversion.
Convert.ToDouble(string) uses Double.Parse(string, CultureInfo.CurrentCulture) method explicitly.
Here how it's implemented;
public static double ToDouble(String value) {
if (value == null)
return 0;
return Double.Parse(value, CultureInfo.CurrentCulture);
}
It is likely your CurrentCulture's NumberFormatInfo.NumberDecimalSeparator property is not . (dot). That's why you can't parse a string with . as a date seperator.
Example in LINQPad;
CultureInfo c = new CultureInfo("de-DE");
c.NumberFormat.NumberDecimalSeparator.Dump(); // Prints ,
As a solution, you can create a new reference of your CurrentCulture and assing it's NumberDecimalSeparator property to . like;
double height;
CultureInfo c = new CultureInfo("de-DE");
c.NumberFormat.NumberDecimalSeparator = ".";
height = Convert.ToDouble("3.14", c);
Judging by the result I take it you are in a culture zone where comma is the normal decimal separator.
Also, I take it that you want both dot and comma to be used for decimal separation.
If not, the below is not the proper solution.
The fastest solution for using both would be
height = Convert.ToDouble(heightString.Replace('.', ',');
This would mean that both dots and comma's are used as comma and thus parsed as a decimal separator.
If you only want to use a dot as separator, you can use invariantculture or a specific numberformatinfo. Invariant culture is already shown in the other posts. numberformat info example:
var nfi = new NumberFormatInfo { NumberDecimalSeparator = "." };
height = double.Parse(heightString,nfi);
For completeness, the example below shows both using numberformatinfo for setting the dot as decimal separator, as well as replacing comma with dots, so both characters are used for decimals
var nfi = new NumberFormatInfo { NumberDecimalSeparator = "." };
height = double.Parse(heightString.Replace(',', '.'),nfi);
Different .Net cultures (countries) have different decimal separators.
If you expect input values to be in some specific format - either use some particular culture or InvariantCulture. Also consider using double.Parse as it geve more flexibility on parsing the values than generic Convert.ToDouble.
var d = double.Parse(heightString, CultureInfo.InvariantCulture);
If you expect user to enter value in local format - your code is fine, but either your expectation of "local format" is wrong, or "current culture" set incorrectly.

why my parsed Double value is not right?

Im trying to parse a string to a Double.
Here is My code:
string a = "10.23";
double b = Double.Parse(a);
but b is 1023.0 and I dont know why. I would like to get 10.23 as a Double
It's because of your culture settings, you may specify culture for Parse method to get desired output:
string a = "10.23";
double b = double.Parse(a, System.Globalization.CultureInfo.InvariantCulture);
// b == 10.23
In Germany the comma (,) is used as the decimal point, whereas most English cultures and your example use the full stop (.) as the decimal point. Since Double.Parse uses the thread default culture to parse numbers, and the thread default culture is set to German, you're getting the wrong result.
You should instead specify the culture explicitly:
using System.Globalization;
string a = "10.23";
double b = Double.Parse(a, CultureInfo.InvariantCulture);
The invariant culture uses the full stop as the decimal point, so I suggest you use that instead. Or if you get the string from a source known to be written using a particular cultural convention, use that culture instead.
Or your location for number formatted, try this my source:
Ext:
public static class Ext
{
public static double? AsLocaleDouble(this string str)
{
var result = double.NaN;
var format = Thread.CurrentThread.CurrentUICulture.NumberFormat;
double.TryParse(str, NumberStyles.AllowDecimalPoint, format, out result);
return result;
}
}
Test:
class Program
{
static void Main(string[] args)
{
var str = "10,23";
Thread.CurrentThread.CurrentUICulture = new CultureInfo("uz-Cyrl-UZ");
Thread.CurrentThread.CurrentCulture = new CultureInfo("uz-Cyrl-UZ");
Console.WriteLine(str.AsLocaleDouble());
Console.ReadKey();
}
}

culturally neutral TryParse

I have the following extension method
public static bool IsValidCurrency(this string value)
{
CultureInfo culture = new CultureInfo ("en-gb");
decimal result;
return decimal.TryParse(value, NumberStyles.Currency, culture, out result);
}
I wish to have this to be culturally neutral allowing to pass $ , €, ¥ etc. into the method
Thanks
Different cultures may use the same currency symbol to mean different things. Hence there is no invariant way to read a currency.
It could however be done in the following way:
public static bool IsValidCurrency(this string value)
{
decimal result;
var cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
return cultures.Any(info => Decimal.TryParse(value, NumberStyles.Currency, info, out result));
}
My initial thought is that passing in a currency symbol to such a method without context means it might be a valid symbol, but not necessarily the correct one - many regions use the '$' symbol, for example.
If I were doing this anyway, I'd probably loop round the specific .NET cultures (avoiding the Invariant Culture, if you're on Windows 7), checking each RegionInfo's CurrencySymbol property against the string passed in. This is quick, dirty (and untested) while it's still in my head; I'm sure this could be more efficiently coded:
public static Boolean IsValidCurrency(this string value)
{
// Assume the worst.
Boolean isValid = false;
foreach (CultureInfo c in CultureInfo.GetCultures(CultureTypes.SpecificCultures))
{
// Account for InvariantCulture weirdness in Windows 7.
if (!c.Equals(CultureInfo.InvariantCulture))
{
RegionInfo r = new RegionInfo(c.LCID);
if (r.CurrencySymbol.Equals(value, StringComparison.OrdinalIgnoreCase))
{
// We've got a match, so flag it and break.
isValid = true;
break;
}
}
}
return isValid;
}
This assumes you're only passing in the symbol, and doesn't solve the variant uses of different symbols. Hope this gets you thinking, anyway.

Format a double value like currency but without the currency sign (C#)

I feed a textbox a string value showing me a balance that need to be formatted like this:
###,###,###,##0.00
I could use the value.ToString("c"), but this would put the currency sign in front of it.
Any idea how I would manipulate the string before feeding the textbox to achieve the above formatting?
I tried this, without success:
String.Format("###,###,###,##0.00", currentBalance);
Many Thanks,
If the currency formatting gives you exactly what you want, clone a NumberFormatInfo with and set the CurrencySymbol property to "". You should check that it handles negative numbers in the way that you want as well, of course.
For example:
using System;
using System.Globalization;
class Test
{
static void Main()
{
NumberFormatInfo nfi = CultureInfo.CurrentCulture.NumberFormat;
nfi = (NumberFormatInfo) nfi.Clone();
Console.WriteLine(string.Format(nfi, "{0:c}", 123.45m));
nfi.CurrencySymbol = "";
Console.WriteLine(string.Format(nfi, "{0:c}", 123.45m));
}
}
The other option is to use a custom numeric format string of course - it depends whether you really want to mirror exactly how a currency would look, just without the symbol, or control the exact positioning of digits.
string forDisplay = currentBalance.ToString("N2");
Have you tried:
currentBalance.ToString("#,##0.00");
This is the long-hand equivalent of:
currentBalance.ToString("N2");
string result=string.Format("{0:N2}", value); //For result like ### ### ##.##
You can do this with the group separator and the section separator, like this:
currentBalance.ToString("#,0.00;(#,0.00)");
This does not account for culture variances like the answer from #JonSkeet would, but this does mimic decimal place, rounding, thousands separation, and negative number handling that en-US culture currency format produces using a single custom format string.
.NET Fiddle Demo
var result = currentBalance.ToString("C").Replace(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencySymbol, "");
CultureInfo cultureInfo = new CultureInfo("en-US");
cultureInfo.NumberFormat.CurrencySymbol = "Rs.";
Thread.CurrentThread.CurrentCulture = cultureInfo;
decimal devimalValue = 3.45M;
this.Text = devimalValue.ToString("C2"); //Rs.3.45
This may be overkill, but it rounds, formats...
#helper TwoDecimalPlaces(decimal? val)
{
decimal x = 0;
decimal y = 0;
string clas = "text-danger";
if (val.HasValue)
{
x = (decimal)val;
if (val > 0)
{
clas = "";
}
}
y = System.Math.Round(x, 2);
IFormatProvider formatProvider = new System.Globalization.CultureInfo(string.Empty);
<span class="#clas">#string.Format("{0:N2}", y)</span>
}
This simple solution works for me with US currency.
If not needing international currency support use this and replace the $ with the currency symbol(s) to be removed:
// for USD
string result = currentBalance.ToString("C").Replace("$", "")
or
// for EUR
string result = currentBalance.ToString("C").Replace("€", "")

Categories