Design Notes: Why Math.floor() does not return ‘int’

This is a commonly asked question. If Math.floor() and Math.ceil() will always return a whole number, why does it return `double` and not another integer type that represents only whole numbers like `int` or `long`? In Java, C#, and JS++, you’ll usually see a method signature as follows:

`public static double floor(double x);`

In actual usage, we may see scenarios such as:

`int x = (int)Math.floor(10.5);`

Hardly pretty. Why was it designed this way? Why couldn’t we just overload Math.floor() to return a different type based on whether we received an int, long, double, etc. argument?

To understand this, we must first understand that Math.floor() can take negative numbers as an argument. For example, Math.floor(-2.5) will return -3. Therefore, if we round down beyond the lowest 32-bit signed integer value (-2,147,483,648), we will no longer be within the range of an `int` (likewise for `long`). On the other end of the spectrum, we have Math.ceil(). If we round up beyond the highest 32-bit signed integer value (2,147,483,647), we will no longer be within the range of an `int` (and, again, likewise for `long`). However, a `double` (IEEE 754 double floating-point type) will fit both an `int` and `long`.

… But you might still be wondering whether or not we can still achieve this correctly through overloading (combined with wrapping or runtime exceptions for overflows)? Let’s assume we did. Math.floor() for an `int` when we receive an `int`, `long` when receive a `long`, etc. Look at this signature for a second; what’s wrong with it?

`public static int floor(int x);`

As you can see, this would defeat the purpose of Math.floor and Math.ceil. Why call Math.floor() on an `int` to receive the same number back?

You’re not going to have a decimal number to floor() or ceil() with `int`, `long`, etc. If we just make all the overloads accept a double argument, can’t we just return a different type? Sadly, no; it would be ambiguous, and it’s impossible to know whether we should return an `int`, `long`, etc. if the argument types were the same. Observe:

```1 2 3 4 5 public static int floor(double x) { ... } public static long floor(double x) { ... }   double x = 1; floor(x); // do we return an int or long here?```

Therefore, despite its inelegance, Math.floor() and Math.ceil() must return a `double`.