I have to convert a double value x into two integers as specified by the following…
“x field consists of two signed 32 bit integers: x_i which represents the integral part and x_f which represents the fractional part multiplied by 10^8. e.g.: x of 80.99 will have x_i as 80 and x_f as 99,000,000”
First I tried the following, but it seems to fail sometimes, giving an xF value of 1999999 when it ought to be 2000000
// Doesn't work, sometimes we get 1999999 in the xF
int xI = (int)x;
int xF = (int)(((x - (double)xI) * 100000000));
The following seems to work in all the cases that I’ve tested. But I was wondering if there’s a better way to do it without the round call. And also, could there be cases where this could still fail?
// Works, we get 2000000 but there's the round call
int xI = (int)x;
double temp = Math.Round(x - (double)xI, 6);
int xF = (int)(temp * 100000000);
The problem is (1) that binary floating point trades precision for range and (2) certain values, such as 3.1 cannot be repsented exactly in standard binary floating point formats, such as IEEE 754-2008.
First read David Goldberg’s “What Every Computer Scientist Should Know About Floating-Point Arithmetic”, published in ACM Computing Surveys, Vol 23, No 1, March 1991.
Then see these pages for more on the dangers, pitfalls and traps of using floats to store exact values:
http://steve.hollasch.net/cgindex/coding/ieeefloat.html
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
Why roll your own when System.Decimal gives you precise decimal floating point?
But, if your going to do it, something like this should do you just fine: