.NET Forum / .NET Framework / New Users / December 2007
Weird double parsing
|
|
Thread rating:  |
Jimmy - 17 Dec 2007 12:21 GMT Hi!
Simply put, the following code:
bool systemOk = true; for (int i=0; i<10000; i++) { double s = double.Parse("-606,11");
if (!s.ToString("0.00").Equals("-606,11")) { systemOk = false; Console.WriteLine("On iteration #{0}. '606,11' was parsed as {1}", i, s); } }
if (systemOk) { Console.WriteLine("No error found!"); }
Console.WriteLine("Press enter to exit..."); Console.ReadLine();
...outputs the following the first run: On iteration #2373. '606,11' was parsed as -606,01 On iteration #8949. '606,11' was parsed as -606,01 On iteration #9338. '606,11' was parsed as -606,01 On iteration #9643. '606,11' was parsed as -606,01 On iteration #9817. '606,11' was parsed as -606,01 Press enter to exit...
...and the following on the second run: On iteration #4944. '606,11' was parsed as -606,01 On iteration #5911. '606,11' was parsed as -606,01 On iteration #8302. '606,11' was parsed as -606,01 On iteration #8518. '606,11' was parsed as -606,01 On iteration #8681. '606,11' was parsed as -606,01 Press enter to exit...
Should I consider suspect a hardware error? I've ran it on other computes with no errors. Any hints on how to test the hardware to verify such hypothesis?
Chris Shepherd - 17 Dec 2007 17:17 GMT > Hi! > [quoted text clipped - 6 lines] > > if (!s.ToString("0.00").Equals("-606,11")) [...]
Maybe I'm silly, but wouldn't this never be true? Shouldn't it be:
if (!s.ToString("0,00").Equals("-606,11"))
Chris.
Jimmy - 17 Dec 2007 17:57 GMT Thanks Chris!
I see your point. You really should be getting curious when you look at the output. Given your question, there should be no output at all... :)
I apologize if this was a bit misleading. The reason is cultural differences, I use a danish culture. Hence, "0.00" becomes "0,00". Console.WriteLine(s.ToString("0.00", System.Globalization.CultureInfo.CreateSpecificCulture("en-US"))); outputs: "-606.11" Console.WriteLine(s.ToString("0.00", System.Globalization.CultureInfo.CreateSpecificCulture("da-DK"))); outputs: "-606,11"
Perhaps the parsing problem itself has something to do with culture settings. I don't know... I've tried different numbers and a common denominator is that it is always a '1' that is wrongly parsed as a '0'. The position of the digit differs from time to time, e.g., 11,11 could be parsed as 11,01 or 10,11
> > Hi! > > [quoted text clipped - 13 lines] > > Chris. Chris Shepherd - 17 Dec 2007 18:24 GMT > I see your point. You really should be getting curious when you look at the > output. Given your question, there should be no output at all... :)
> I apologize if this was a bit misleading. The reason is cultural > differences, I use a danish culture. Hence, "0.00" becomes "0,00". [quoted text clipped - 4 lines] > System.Globalization.CultureInfo.CreateSpecificCulture("da-DK"))); > outputs: "-606,11" It wasn't misleading of you, and I was aware it's a cultural difference, I just assumed that you would have to use the culture-specific proper syntax on ToString. That appears to be completely wrong of me. It's odd your code doesn't work, because if I create a culture object for da-DK it works fine -- this code is working correctly for me:
CultureInfo dk = CultureInfo.CreateSpecificCulture("da-DK"); string stringVal = "-606,11";
bool systemOk = true; for (int i = 0; i < 10000; i++) { double s = double.Parse(stringVal, dk);
if (!s.ToString("0.00",dk).Equals(stringVal)) { systemOk = false; Console.WriteLine("On iteration #{0}. '{1}' was parsed as {2}", i, stringVal, s); } }
if (systemOk) { Console.WriteLine("No error found!"); }
Console.WriteLine("Press enter to exit..."); Console.ReadLine();
Chris.
Chris Shepherd - 17 Dec 2007 18:29 GMT > It wasn't misleading of you, and I was aware it's a cultural difference, > I just assumed that you would have to use the culture-specific proper > syntax on ToString. That appears to be completely wrong of me. > It's odd your code doesn't work, because if I create a culture object > for da-DK it works fine -- this code is working correctly for me: [...]
To be clear, by "this code is working correctly for me" I mean that I simply get the "No errors found!" message followed by "Press enter to exit..." with no appearance of any of the "On iteration #" messages.
Chris.
Peter Duniho - 17 Dec 2007 18:20 GMT >> if (!s.ToString("0.00").Equals("-606,11")) > [...] > > Maybe I'm silly, but wouldn't this never be true? Shouldn't it be: > > if (!s.ToString("0,00").Equals("-606,11")) Nope. The format string uses only the period for decimal, regardless of what the actual decimal separator is set to for the system, and the comma is specifically for something else (thousand separator or number scaling, depending on context). This allows a format string to be language-independent.
The output from the program proves that the if() condition works as expected, since it is true occasionally.
Unfortunately, I don't have any useful information regarding the behavior the OP is seeing. Hardware errors are rare, and I have seen at least one other example of floating point operations being affected by other things going on in the computer (code that leaves the FPU in an unusual state). But the error in this case is much greater than that noted in the other example I saw; a floating point error that's just part of the normal operation of the FPU should be _much_ smaller than that.
One thing about the posted code is that it relies on the formatting code, which means the error could be happening in the parse, or the format back to a string. It would be useful and interesting to change the test so that it's two different loops, one that repeatedly parses the string, but compares it to a constant double instead of formatting it again, and another that starts with a constant double and repeatedly parses it.
That would help narrow down the problem, to identify whether it happens only when parsing, only when formatting, or in neither case separately (in other words, the two operations are interacting somehow to cause the error). I suppose it's possible the test would reveal errors in both operations, but that seems unlikely to me.
I don't have enough knowledge to know how to _use_ that information, but it would at least hopefully help understand the error better.
Pete
Chris Shepherd - 17 Dec 2007 18:28 GMT > Nope. The format string uses only the period for decimal, regardless of > what the actual decimal separator is set to for the system, and the [quoted text clipped - 4 lines] > The output from the program proves that the if() condition works as > expected, since it is true occasionally. Actually, it was *always* true for me. I could never get it to not always either be true or false, even over 90000 iterations instead of 10000.
Are you seeing different results?
Chris.
Peter Duniho - 17 Dec 2007 18:49 GMT > [...] >> The output from the program proves that the if() condition works as [quoted text clipped - 5 lines] > > Are you seeing different results? I haven't even tried to run it. By "is true occasionally" I just mean on the OP's computer.
I assume you mean that the result of the Equals() method is true. The clause itself should always be _false_ on a computer that doesn't demonstrate the error (and as the OP says, so far he's only been able to reproduce it on his own computer...the code doesn't detect any error on a different computer).
Pete
Jimmy - 17 Dec 2007 18:41 GMT Good idea. Tested with code: bool systemOk = true; Console.WriteLine("Testing with string comparison..."); for (int i=0; i<10000; i++) { double s = double.Parse("-606,11"); if (!s.ToString("0.00").Equals("-606,11")) { systemOk = false; Console.WriteLine("On iteration #{0}. '-606,11' was parsed as {1}", i, s); } }
const double doubleCompare = -606.11d; Console.WriteLine("Testing with double comparison..."); for (int i=0; i<10000; i++) { double s = double.Parse("-606,11"); if (s!=doubleCompare) { systemOk = false; Console.WriteLine("On iteration #{0}. '-606,11' was parsed as {1}", i, s); } } if (systemOk) { Console.WriteLine("No error found!"); }
Console.WriteLine("Press enter to exit..."); Console.ReadLine();
Result: Testing with string comparison... On iteration #1016. '-606,11' was parsed as -606,01 On iteration #1055. '-606,11' was parsed as -606,01 On iteration #3110. '-606,11' was parsed as -606,01 On iteration #4366. '-606,11' was parsed as -606,01 On iteration #7388. '-606,11' was parsed as -606,01 On iteration #9022. '-606,11' was parsed as -606,01 Testing with double comparison... On iteration #5. '-606,11' was parsed as -606,01 On iteration #594. '-606,11' was parsed as -606,01 On iteration #2242. '-606,11' was parsed as -606,01 On iteration #3648. '-606,11' was parsed as -606,01 On iteration #9918. '-606,11' was parsed as -606,01 Press enter to exit...
Weird!
> >> if (!s.ToString("0.00").Equals("-606,11")) > > [...] [quoted text clipped - 37 lines] > > Pete Peter Duniho - 17 Dec 2007 18:55 GMT > Good idea. Tested with code: Well, the code you posted isn't exactly what I meant. Try this:
bool systemOk = true; Console.WriteLine("Testing formatting..."); const double doubleCompare = -606.11d; for (int i=0; i<10000; i++) { string strT = doubleCompare.ToString("0.00");
if (!strT.Equals("-606,11")) { systemOk = false; Console.WriteLine("On iteration #{0}. '-606,11' was formatted as {1}", i, strT); } }
Console.WriteLine("Testing parsing..."); for (int i=0; i<10000; i++) { double s = double.Parse("-606,11"); if (s!=doubleCompare) { systemOk = false; // WARNING: if there's an error in the formatting, then the output here is // suspect, because it relies on the formatting to display the double! :) Console.WriteLine("On iteration #{0}. '-606,11' was parsed as {1}", i, s); } } if (systemOk) { Console.WriteLine("No error found!"); }
Console.WriteLine("Press enter to exit..."); Console.ReadLine();
Jimmy - 18 Dec 2007 09:04 GMT Ah, I see. The error only occur in relation to double.Parse. A ToString from a double will not produce this error.
Here's probably the strangest piece of code I've written - the workaround (taken from its context of course) :)
string tmpStr = thedoublestring; // eg. -606.11 double s; string sStr; do { s = double.Parse(tmpStr); sStr = s.ToString("0.000000"); } while (!sStr.Equals(columns[selectedBeloebColumns[i]]));
> > Good idea. Tested with code: > [quoted text clipped - 38 lines] > Console.WriteLine("Press enter to exit..."); > Console.ReadLine();
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|