I'm not sure if I'm missing something here but there seems to be a bug in the System.Math.Round function from the .NET 2.0
For example, this code:
Math.Round(4175 /1000, 1)
Returns:
4.1999998092651367
The exact same code compiled in VB2003 (.NET 1.1) returns:
4.2
Does anyone knows why is this

System.Math.Round(Double, Integer) bug?
HCTwinJava
However, the bug is not in the Math.Round function. A Double variable cannot accurately represent a value like 0.33 so those extra digits you see are what is actually stored in there.
The bug appears to be with the ToString method. For whatever reason, Double.ToString with no format arguments does its own output rounding before the Direct3D device has been created, but does no automatic rounding afterwards.
I could reproduce the bug with your test program as-is, with the Visual Studio 2005 debugger, with a Visual Basic console variant, and with a C# console variant of your program.
I suggest you file this bug with the MSDN Product Feedback website (http://lab.msdn.microsoft.com/productfeedback/). They'll be happy since you already have a nice program for reproduction!
FrankSp
Thank you for that link. It is a very interesting reading... however, the problem I'm having with Math.Round is more serious than that caused by the limitations of handling floating point numbers.
To test my theory (that being, that there's a serious bug with the Math.Round function) I have run some additional tests (quite simple tests):
NOTE: Remember that the function does work fine (meaning -- it produces predictable results) before instantiating the Direct3D device. The following results are obtained right after calling this line of code:
mDevice = New D3D.Device(0, D3D.DeviceType.Hardware, Instance, D3D.CreateFlags.MixedVertexProcessing, mPresentParams)
Test 1: A simple rational number:
Math.Round(3256 / 100, 2)
Produces:
32.560001373291016
Test 2: A simple periodic decimal number:
Math.Round(1 / 3, 2)
Produces:
0.33000001311302185
Test 3: A complex irrational number:
Math.Round(Math.PI, 2)
Produces:
3.1400001049041748
Again, remember that the interesting thing is that the above tests return the expected results right before the Direct3D device is created and that this works just fine if the application is compiled using VS 2003
Giftednewt
pkshih
http://software.xfx.net/ftp/RoundBug.zip
JaLG
I'm unable to reproduce the problem you are seeing. I'm using Visual Studio 2005 the release version. When I run the code you reference, .NET 2.0 properly returns a 4.2. Are you running one of the Beta/RC versions
Thanks,
Bill
Carl Rosenberger
JDeas
Please see Jon Skeet's article for a discussion of FP arithmetic:
http://www.yoda.arachsys.com/csharp/floatingpoint.html
Gimlei
Chris,
Once again, thank you for the information.
I have just submitted the bug: http://lab.msdn.microsoft.com/ProductFeedback/viewFeedback.aspx feedbackId=FDBK40230
Perhaps you could add the information about your suspicion that this may be a problem with the Double.toString function and not directly related to the Round function.
You are obviously more knowledgeable than me in this area and your comments might help Microsoft troubleshoot and resolve the problem.
IamJunk
I'm using the final version.
Here's some more information:
I loaded a different project (a very simple Windows Form application) and tested the code in the immediate window and it worked.
Then, I loaded the project where I'm having the problem (a rather complex Class Library) and the Math.Round function fails as described in my first post.
So, here's what I did: I started debugging the application by pressing F8 and then testing the code in the immediate window; it worked.
Kept pressing F8 going from line to line and before executing a new line I tested the code. After several hundreds lines of code I found that the error occurs right after executing this line of code:
mDevice =
New D3D.Device(0, D3D.DeviceType.Hardware, Instance, D3D.CreateFlags.MixedVertexProcessing, mPresentParams)If you evaluate the code before the above line of code it returns 4.2, evaluate it immediately after and it returns 4.19999...
Interesting uh
ram1608
When you create a Direct3D device, the FPU is switched to single precision, and there are no longer enough digits of precision to accurately do the calculation.
You can avoid all of this by simply telling Direct3D not to mess with the FPU at all. When creating the device you should use the CreateFlags.FpuPreserve flag to keep the CLR's double precision, and have your code functioning as you expect it.
jony_cool
You have to press the Upload button (or whatever it's called) after entering the file path and before submitting your bug report. The website does not automatically upload the attachment when you click Submit (or whatever it's called).
I think you can still add the attachment by editing the bug report.
Remcodo
I tried the FpuPreserve flag and it worked.