Floating Point Problems

  • Thread starter Thread starter O.B.
  • Start date Start date
O

O.B.

int minutesOriginal = 4;
double secondsOriginal = 0.42;

double myvalue = minutesOriginal*60 + secondsOriginal;

int minutes = (int)(myvalue/60);
double seconds = myvalue%60;
double seconds2 = myvalue - (minutes*60);

seconds and seconds2 both equal 0.41999999999998749. I want 0.42
instead (no additional rounding calculations required). Is there
another way to ensure that we get exactly what is stored?
 
Since 0.42 / 60 comes out to exactly 0.007, you could, in this instance, use
the Decimal data type instead of double.
 
int minutesOriginal = 4;
double secondsOriginal = 0.42;

double myvalue = minutesOriginal*60 + secondsOriginal;

int minutes = (int)(myvalue/60);
double seconds = myvalue%60;
double seconds2 = myvalue - (minutes*60);

seconds and seconds2 both equal 0.41999999999998749.  I want 0.42
instead (no additional rounding calculations required).  Is there
another way to ensure that we get exactly what is stored?

In general no, there is no another way that guarantees always proper
answer for all real numbers. This is the limitation of floating point
computer representation that always has some limited accuracy except
few selected numerical values. You can get better accuracy with
decimal thanks to slightly different internal representation and
higher number of which accounts for more accuracy but decimal has
similar limitations. For example it is incapable to represent 1/3
precisely so you can always come up with some iterative process that
will reinforce initial discrepancy in internal representation to such
magnitude that the outcome will be eventually meaningless. If you will
alwyas stay with two digit decimal fractions, multiplication and
modulus division then decimal will remain precise. If however you will
introduce division by 3, 7 etc. then neither binary nor decimal
representation will do you any good. You will need an algebraic
library with internal fraction capability to remain precise in the
rational numbers domain. Most irrational numbers cannot be represented
precisely at all in any traditional numerical notation.

JAM
 
O.B. said:
int minutesOriginal = 4;
double secondsOriginal = 0.42;

double myvalue = minutesOriginal*60 + secondsOriginal;

int minutes = (int)(myvalue/60);
double seconds = myvalue%60;
double seconds2 = myvalue - (minutes*60);

seconds and seconds2 both equal 0.41999999999998749. I want 0.42
instead (no additional rounding calculations required).

There is no such thing. The decimal number "0.42" cannot be represented
exactly in binary floating point. Even "secondsOriginal" is just an
approximation.
Is there another way to ensure that we get exactly what is stored?

You ARE getting exactly what is stored. What you need to do is PRESENT it
in the right way. If you want 2 decimals, then print it with a 2 decimal
format. Any attempt you make to round the intermediate results will merely
confuse the results even more.
 
Math.Round is the way to go.

And in case it comes up, as far as I know the only "right" way to check for
zero on a floating point number is:

if ( Math.Abs(myvalue) < Double.Epsilon ) {
...
}

In fact, I wonder why they even implemented the == operator on floating
point types?

Josh
 
Back
Top