TheCloudlessSky
TheCloudlessSky

Reputation: 18353

Why doesn't Math.Round/Floor/Ceiling return long or int?

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

Answers (4)

Peter
Peter

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

Mark Byers
Mark Byers

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

(Source)

Upvotes: 33

dan04
dan04

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

bwawok
bwawok

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

Related Questions