Converting from floating point numbers (e.g. double, single) to integers can be tricky. And when not done carefully some very “strange” results can occur especially when complex mathematical calculations were involved.

To demonstrate this, look at the code given below:

double d = 0.1d;

double t = 0.0d;

for (int i = 1; i < 200; i++) {

t = i * d;

double temp = t / d;

int r = (int)(temp); ;

if (r != i)

Console.WriteLine(“{0} : {1}”, r, i);

}

What the code really does is comparing the values between i and i * d / d. So should they be the same? As you can see for the most of the time, the two values are identical, except for the following cases:

42 : 43

80 : 81

85 : 86

90 : 91

161 : 162

166 : 167

171 : 172

176 : 177

181 : 182

186 : 187

And there are no particular patterns to the error. This error does not manifest it self most of the time so it is easy to ignore (e.g. if we were only outputting values between 1 and 30, we wouldn’t see this error).

This is an inherent problem to all floating point types. To see why this happened, take a look at what temp was when i was 43. At that time temp was supposed to be exactly 43, but it was actually 42.999999999999993 due to the loss of precision during floating point calculation. A type cast is equivalent of truncation.

To correct this problem, we will need to add a small amount to the converted value. For instance:

int r = (int)(temp + 1e-10);

Actually, the result would also be correct if we simply perform a rounding operation. That is:

int r = (int)(temp + 0.5);

And in C# you can use the built-in function Math.Round() instead:

int r = (int) Math.Round(temp);

This simple example illustrated how rounding error occurs in the most unlikely situation and. We must take extra caution to round the result when converting number to an integer type.

Be Sociable, Share!