Reputation: 18353
Every time I use Math.Round/Floor/Ceiling
I always cast to int
(or perhaps long
if necessary). Why exactly do they return double
if it's always returning an integer?
Upvotes: 26
Views: 11029
Reputation: 21
Range arguments aside, none of these answers addresses what, to me, is a fundamental problem with returning a floating point number when you really want an exact integer. It seems to me that the calculated floating point number could be less than or greater than the desired integer by a small round off error, so the cast operation could create an off by one error. I would think that, instead of casting, you need to apply an integer (not double) round-nearest function to the double result of floor()
. Or else write your own code. The C library versions of floor()
and ceil()
are very slow anyway.
Is this true, or am I missing something? There is something about an exact representation of integers in an IEEE floating point standard, but I am not sure whether or not this makes the cast safe.
I would rather have range checking in the function (if it is needed to avoid overflow) and return a long. For my own private code, I can skip the range checking. I have been doing this:
long int_floor(double x)
{
double remainder;
long truncate;
truncate = (long) x; // rounds down if + x, up if negative x
remainder = x - truncate; // normally + for + x, - for - x
//....Adjust down (toward -infinity) for negative x, negative remainder
if (remainder < 0 && x < 0)
return truncate - 1;
else
return truncate;
}
Counterparts exist for ceil()
and round()
with different considerations for negative and positive numbers.
Upvotes: 2
Reputation: 838216
The result might not fit into an int (or a long). The range of a double is much greater.
Approximate range of double: ±5.0 × 10−324 to ±1.7 × 10308
Upvotes: 33
Reputation: 90995
I agree with Mark's answer that the result might not fit in a long
, but you might wonder: what if C# had a much longer long
type? Well, here's what happens in Python with it's arbitary-length integers:
>>> round(1.23e45)
1229999999999999973814869011019624571608236032
Most of the digits are "noise" from the floating-point rounding error. Perhaps part of the motivation for Round
/Floor
/Ceiling
returning double
in C# was to avoid the illusion of false precision.
An alternative explanation is that the .NET Math
module uses code written in C, in which floor and ceil return floating-point types.
Upvotes: 8
Reputation: 15347
There is no reason given on the docs that I could find. My best guess is that if you are working with doubles, chances are you would want any operations on doubles to return a double. Rounding it to cast to an int was deemed by the language designer less common then rounding and keeping as a double.
You could write your own method that cast it to an int for you in about 2 lines of code, and much less work than posting a question on stack overflow...
Upvotes: -3