Incorrect values when using float.Parse(string)

  • Thread starter Thread starter trevor
  • Start date Start date
T

trevor

Incorrect values when using float.Parse(string)

I have discovered a problem with float.Parse(string) not getting values
exactly correct in some circumstances(CSV file source) but in very
similar circumstances(XML file source) and with exactly the same value
it gets it perfectly correct all the time.

These are the results I got, XML is always correct, CSV are only
incorrect for some of the values (above about 0.01) but always gives
the same incorrect value.

StringValue XMLfloat CSVfloat
0.001380697 0.001380697 0.001380697 OK
0.008801419 0.008801419 0.008801419 OK
0.011789167 0.011789167 0.0117891673 Error
1.115063567 1.115063567 1.11506355 Error
2.233219287 2.233219287 2.23321939 Error

As you can see in the (CSV file source) I have tried parsing to double
then to float but the error still accurse when going into float.
The two bits of code are in the same class just different methods.

Are there any environmental parameters that can affect the way floats
operate?

XML file source
private static float GetAttributeFloat(XmlAttributeCollection
_Attributes, AttributeName _AttributesName)
{
float _ValidFloat = 0.0F;
foreach(XmlAttribute _Attribute in _Attributes)
{
if(Equals(_Attribute.Name,_AttributesName))
{
try
{
_ValidFloat = float.Parse(_Attribute.Value);
}
catch(Exception)
{ }
}
}
return _ValidFloat;
}

CSV file source
int[] CurveADC = new int[EnergyCompTableValues];
float[] CurveDose = new float[EnergyCompTableValues];
for(int y=0;y < EnergyCompTableValues;y++)
{
// CurveADC[y] = int.Parse(CalData[CalDataIndex++]);
// float temp = 0.0F;
// string datas = CalData[CalDataIndex++];
// double temp2 = Convert.ToDouble(datas);
// float temp3 = (float)temp2;
// temp = float.Parse(datas,new
System.Globalization.CultureInfo("en-GB", true));
// CurveDose[y] = temp;
CurveDose[y] = float.Parse(CalData[CalDataIndex++]);
}



Background info:
Basically I have got two files XML & CSV format which contain
identically the same data. The data is converted into a binary image
for uploading into hardware, which ever file is used identical binary
images are required.
 
Well, float.Parse yelds as below (as the default .ToString()), as does the
number itself (evaluated at the immediate window):

?float.Parse("1.115063567")
1.11506355
?1.115063567F
1.11506355
?1.115063567F==float.Parse("1.115063567")
true

Are you sure the problem isn't formatting? And note that floating points are
*by definition* not exact.
I can't recall the format specifier to get the full value, but I'm also not
100% that it is actually there...

Marc
 
trevor said:
Incorrect values when using float.Parse(string)

I have discovered a problem with float.Parse(string) not getting
values exactly correct in some circumstances(CSV file source) but in
very similar circumstances(XML file source) and with exactly the same
value it gets it perfectly correct all the time.

These are the results I got, XML is always correct, CSV are only
incorrect for some of the values (above about 0.01) but always gives
the same incorrect value.

StringValue XMLfloat CSVfloat
0.001380697 0.001380697 0.001380697 OK
0.008801419 0.008801419 0.008801419 OK
0.011789167 0.011789167 0.0117891673 Error
1.115063567 1.115063567 1.11506355 Error
2.233219287 2.233219287 2.23321939 Error

You're expecting more from floating point math than it can provide. See

http://docs.sun.com/source/806-3568/ncg_goldberg.html

In a nutshell, a float has about 8 significant digits. The two values
you've shown above differ in the 9th significant digit. This may be due to
a single bit difference in the float representation, or, more likely, is
related to the specific sequence of widening and narrowing conversions that
the two code paths exhibit - particularly on the output (conversion from
float to string) side.

Have you compared the binary representations of the Xml- and Csv-derived
floats to see if they're really different? Despite the various oddities
that are seen with floats, it would seem reasonable to expect that
float.Parse(str) will always return the same value for a given sequence of
characters, although I can't see anything obvious in the .NET documentation
that guarantees that.

-cd
 
Im fixed to using floats due to hardware that the binary image ends up.

Yes the binary image is different by as much as 2 or 3 bits, this is
what led me to tracking it back to the float problem.

I have even created a little method just for the float parsing, both
CSV & XML processing call this but still produce the different results.

Yes I would expect identical strings to give identical results
regardless of the situation, it must use the same underlying code.
 
To be honest, I don't think float.Parse is the culprit here. I can't believe
it would return different things for the same string.

Are you sure you are reading the CSV correctly? The code to fill CalData
isn't shown, but I would be *very* interested to see what the ?strings?
actually are inside this array. The floating point accuracy will prevent you
getting the number you first thought of, but it should be possible to get
the same number via either route. The following works just fine (although
you do get minor variance from the input values):

static void Main() {
const string xml = @"
<xml a=""0.011789167""
b=""1.115063567""
c=""2.233219287""/>";
const string csv = "0.011789167,1.115063567,2.233219287";
float[,] data = new float[3,2];
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
int index = 0;
foreach(XmlAttribute xmlValue in doc.DocumentElement.Attributes) {
data[index++, 0] = float.Parse(xmlValue.Value);
}
index = 0;
foreach (string csvValue in csv.Split(',')) {
data[index++, 1] = float.Parse(csvValue);
}
for (int i = 0; i < 3; i++) {
float v1 = data[i, 0], v2 = data[i,1];
Debug.WriteLine(string.Format("{0} vs {1}: {2}",
v1.ToString("E12"), v2.ToString("E12"), v1 == v2 ? "OK" : "Error"));
}
}
 
Marc Gravell said:
I forgot to say... you are operating very close to the limit of floats...
suggest you switch to doubles (or decimals if they fit your data; check the
range).

Might also want to read:

http://www.extremeoptimization.com/resources/Articles/FPDotNetConceptsAndFormats.aspx
or
http://www.yoda.arachsys.com/csharp/floatingpoint.html

(Jon: your online "exact double" page still points to aspspider, which is a
404... probably not critical though)

Cheers - aspspider keeps losing my account, so I need to keep
reuploading the content. Thanks for pointing it out :)
 

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

Back
Top