Conversions between float and string

G

Gustaf Liljegren

Values altered when I convert from string to float and back again:

using System;

class FloatTest
{
static void Main(string[] args)
{
string var1 = "800856.22";
Console.WriteLine(var1);
float var2 = Convert.ToSingle(var1.Replace(".", ","));
Console.WriteLine(var2.ToString());
}
}

My output:

800856.22
800856,3

The input data use period as decimal point, while the computers that
will run this program use comma (due to the regional settings in
Windows). That's why I do the Replace(). I'm amazed that the
ToSingle() method doesn't handle period and comma equivalently. How
would I do if I needed to distribute the program internationally?

The big problem is the alteraion of value. The program handles account
balances, so there must be no alterations like this. What am I doing
wrong?

Gustaf
 
J

Jon Skeet [C# MVP]

Gustaf Liljegren said:
Values altered when I convert from string to float and back again:

using System;

class FloatTest
{
static void Main(string[] args)
{
string var1 = "800856.22";
Console.WriteLine(var1);
float var2 = Convert.ToSingle(var1.Replace(".", ","));
Console.WriteLine(var2.ToString());
}
}

My output:

800856.22
800856,3

The input data use period as decimal point, while the computers that
will run this program use comma (due to the regional settings in
Windows). That's why I do the Replace(). I'm amazed that the
ToSingle() method doesn't handle period and comma equivalently. How
would I do if I needed to distribute the program internationally?

You'd use the versions of Single.Parse and Single.ToString which take
an IFormatProvider, and pass the appropriate CultureInfo for what you
expect to receive/want to produce.
The big problem is the alteraion of value. The program handles account
balances, so there must be no alterations like this. What am I doing
wrong?

You're expecting floats to carry more information than they do. If you
do:

float f = 800856.22f;
Console.WriteLine (f);

you'll get the same error. In fact, the single that is produced is
exactly 800856.25, but the formatting is rounding off to 800856.3. (If
you want to see exact values for singles/doubles, see
http://www.pobox.com/~skeet/csharp/floatingpoint.html and look for
DoubleConverter.)
 
S

Sheila Jones

Hello,

There are two possible problems here. Firstly, the value 800856.22 may be
too precise to be held in a Single, so is being rounded to something else.
Or, the value may be held correctly, but is being rounded to 7 signifcant
digits when converted to a string - in other words, "800856,3" may not be
the actual value of var2.

I would use Doubles instead, e.g
double var2 = Convert.ToDouble(var1);

I hope that helps.
 
G

Gustaf Liljegren

Jon Skeet said:
You'd use the versions of Single.Parse and Single.ToString which take
an IFormatProvider, and pass the appropriate CultureInfo for what you
expect to receive/want to produce.

Thank you both. And excellent reading about floating-point numbers!
I've been looking for something like this article. Using decimal
instead of float solved my problem.

Using IFormatProvider, is there a way to make the program "sensitive"
to the computers region, so that these conversions never fail? I
wasn't able to figure out how to use the class.

Gustaf
 
J

Jon Skeet [C# MVP]

Gustaf Liljegren said:
Thank you both. And excellent reading about floating-point numbers!
I've been looking for something like this article. Using decimal
instead of float solved my problem.

Thanks :)
Using IFormatProvider, is there a way to make the program "sensitive"
to the computers region, so that these conversions never fail? I
wasn't able to figure out how to use the class.

The normal thing to do is pass one of CultureInfo.CurrentUICulture,
CultureInfo.CurrentCulture or CultureInfo.InvariantCulture - but I
don't think there's a culture which allows *both* in the parsing, if
that's what you were after.
 
J

Julie J.

Use the decimal type instead. It provides the level of fractional precision
that you require.

Also, use Parse instead to convert:

decimal var2 = decimal.Parse(var1);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top