If you get a format exception, that means that the culture you are running your code on does not use the .
character for its decimal separator. There are several things you can do:
- Change your global culture to one that uses the
.
character as its decimal separator
- Manually replace the
.
character with your culture's decimal separator
- Call an overload of the various parse methods that takes in an
IFormatProvider
instance
I consider the third option to be the best by far. It lets you specify what format the parse method expects. The CultureInfo
class implements the IFormatProvider
interface. In your code, you expect the .
character to be the decimal separator. This is true in several cultures, but your safest choice is probably the InvariantCulture
.
You can modify your code then as follows:
string s1 = "2";
string s2 = "25.00";
double d1 = Convert.ToDouble(s1, CultureInfo.InvariantCulture);
double d2 = Convert.ToDouble(s2, CultureInfo.InvariantCulture);
double d3 = d2 * d1;
string s1 = "2";
string s2 = "25.00";
double d1 = double.Parse(s1, CultureInfo.InvariantCulture);
double d2 = double.Parse(s2, CultureInfo.InvariantCulture);
double d3 = d2 * d1;
string s1 = "2";
string s2 = "25.00";
float f1 = float.Parse(s1, CultureInfo.InvariantCulture);
float f2 = float.Parse(s2, CultureInfo.InvariantCulture);
float f3 = f2 * f1;
Here, the CultureInfo
class' NumberFormat
property is used to determine the decimal separator used when parsing the string to a double
or float
.
I have created a .NET Fiddle to show you that it works: https://dotnetfiddle.net/Z5HB4T
You can see what the decimal separator is for a specific culture by using the NumberDecimalSeparator
property of the CultureInfo
's NumberFormat
property:
// Returns: "."
CultureInfo.InvariantCulture.NumberFormat.NumberDecimalSeparator;
// Outputs: "."
new CultureInfo("en-US").NumberFormat.NumberDecimalSeparator;
// Returns: ","
new CultureInfo("nl-NL").NumberFormat.NumberDecimalSeparator;
// Returns: "<depends on what is set as the current culture>"
CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
See it in action at: https://dotnetfiddle.net/nSbYoP
What is interesting, is that the NumberFormat
property is of type NumberFormatInfo
which also implements IFormatProvider
! This means that you could also pass a NumberFormatInfo
instance to the parse methods. This allows you to create a number format fully to your liking. We could then use any decimal number separator string we like. The following examples changes the decimal number separator to the #
character:
var numberFormatInfo = new NumberFormatInfo();
numberFormatInfo.NumberDecimalSeparator = "#";
string s1 = "2";
string s2 = "25#00";
double d1 = Convert.ToDouble(s1, numberFormatInfo);
double d2 = Convert.ToDouble(s2, numberFormatInfo);
double d3 = d2 * d1;
See: https://dotnetfiddle.net/h6ex2Z
This approach gives your total freedom on how you want the parse methods to interpret numbers.