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();
}
}
Related
There are lot of format specifier in .net e.g. C for currency, D for decimal.
Lot of defined formats can be here.
How can I get exact format behind format specifier as per given locale.
E.g. (I assume here en-US locale)
GetFormatSpecifierText("C") should return me "$" #,##0.00
GetFormatSpecifierText("F") should return me "#,##0.00
Look at how Culture is used in combination with the format specifiers. I believe you may be looking for the override in the below code from MSDN:
public class userOverrideSample
{
[WebMethod]
public String UserLocalSetting()
{
int i = 100;
// Sets the CurrentCulture to French in France.
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
// Displays i formatted as currency for the CurrentCulture.
// Due to operating system differences, you cannot be sure what currency
// symbol will be used.
return (i.ToString("c"));
}
[WebMethod]
public String OverrideUserSetting()
{
int i = 100;
// Sets the CurrentCulture to French in France.
// Uses the CultureInfo constructor that takes a
// useUserOverride parameter.
// Sets the useUserOverride value to false.
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR", _
false);
// Displays i formatted as currency for the CurrentCulture.
// This will override any user settings and display the euro symbol.
return (i.ToString("c"));
}
}
I write below code to get currency format pattern.
Here, passed param numberFormat as [Currency]#,##0.00 and fr-FR locale; and got # ##0,00 "€" as desire and expected o/p.
static string[] CurrencyPositivePattern = { "$n", "n$", "$ n", "n $" };
static string[] CurrencyNegativePattern = { "($n)", "-$n", "$-n", "$n-", "(n$)",
"-n$", "n-$", "n$-", "-n $", "-$ n",
"n $-", "$ n-", "$ -n", "n- $", "($ n)",
"(n $)" };
internal static string GetCurrencyPattern(System.Globalization.NumberFormatInfo numberFormatInfo, string numberFormat)
{
numberFormat = numberFormat.Replace("[Currency]", string.Empty);
int pos = numberFormatInfo.CurrencyPositivePattern;
int neg = numberFormatInfo.CurrencyNegativePattern;
string currencySymbol = string.Format("\"{0}\"", numberFormatInfo.CurrencySymbol);
string excelPattern = string.Concat(CurrencyPositivePattern[pos].Replace("n", numberFormat).Replace("$", currencySymbol),
";",
CurrencyNegativePattern[neg].Replace("n", numberFormat).Replace("$", currencySymbol));
return excelPattern;
}
Few References that I used for implementation:
https://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.currencynegativepattern(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.currencypositivepattern(v=vs.110).aspx
As I stucked at specific Currency format for excel, I write Currency specific code. Others formats are easily handled by excel (same also commented by Murray Foxcroft in answer's comment).
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.
In C# im trying to format an amount according to the setup on the computer.
So for instance if the setup on en-US are xxxx.xx (separated by an dot) and in nb-NO it is xxxx.xx (separated by an comma) I want to auto-detect that and format the amount accordingly.
Thanks for your help in advance.
Try this
double amount = xxxx.xx;
string formattedCurrency=amount.ToString("C", CultureInfo.CurrentCulture);
If you're just looking to get the value formatted as a currency (as a string), you can do this:
MyDecimal.ToString("c");
If you're looking for certain properties, you can look in a particular culture's NumberFormat property, which is of type NumberFormatInfo.
This class contains properties which tell you the culture's thousands separator, decimal separator, currency symbol, how to handle negative numbers etc.
Useful properties for currencies:
CurrencyDecimalSeparator
CurrencySymbol
NumberDecimalSeparator
you can use Two Interface IFormatProvider, ICustomFormatter,to Create you Format:
public class TestConvertor: IFormatProvider, ICustomFormatter
{
public object GetFormat(Type formatType)
{
if (formatType == typeof(ICustomFormatter))
return this;
return null;
}
public string Format(string format, object arg, IFormatProvider formatProvider)
{
decimal amount = arg is decimal ? (decimal) arg : 0;
return amount.ToString("C", CultureInfo.CurrentCulture);
}
}
class Program
{
static void Main(string[] args)
{
double amount = 2541.25;
var f = string.Format(new TestConvertor(), "{0:Currency}", 2545);
Console.WriteLine(f);
Console.ReadKey();
}
}
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);
}
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("€", "")