# pseudoramble

## I Still Dont Know JS

Some days, I get complacent. So complacent, in fact, that I let myself slip into thinking I know Javascript. If this fact alone doesn't make you sigh, well, thanks for your understanding. Here was today's unexpected adventure.

## What's wrong with the code?

``````    /**
* Given a number, decrease it by 1, or stop it at the specified min.
* @param {number} value - The value to decrease
* @param {number} min - The limit which the value can reach. Defaults to Number.MIN_VALUE.
* @returns {number} - Either value -1 or min.
*/
function decrement(value, min = Number.MIN_VALUE) {
const nextValue = value - 1;
return Math.max(nextValue, min);
}
``````

This code is not trying to be sneaking or misleading at all. It takes one of the existing value. If it finds that `min` value is larger than `nextValue` it returns `min`. Otherwise it returns `nextValue`. Here are some examples:

``````    decrement(10, 5);     //    9  OK
decrement(-100, -101) // -101  OK
decrement(-101, -101) // -101  OK
``````

So far, so good. Don't forget to test that default argument:

``````    decrement(10)   //      9  OK
decrement(-100) // 5e-324  OK wait what?
decrement(-1)   // 5e-324  :
decrement(0)    // 5e-324  Oh no...
``````

What can we gather from this? Well, first thing is that it seems like this oddball result is the same. That means we get the same branch on each run. What else can we tell?

``````    decrement(0.9999)  // 5e-324                   Bad
decrement(1.9999)  // 0.9999                   OK
decrement(1.0001)  // 0.00009999999999998899   OK
``````

We can see when our function maps to a number <= 0 that we get this funny result. Huh...

So what's happening? MDN, tell me about `MAX_VALUE`!:

The `Number.MAX_VALUE` property represents the maximum numeric value representable in JavaScript.

...

The `MAX_VALUE` property has a value of approximately `1.79E+308`.

OK, that sounds right. So naturally `MIN_VALUE` is the opposite?

The `Number.MIN_VALUE` property represents the smallest positive numeric value representable in JavaScript.

...

The `MIN_VALUE` property is the number closest to `0`, not the most negative number, that JavaScript can represent. `MIN_VALUE` has a value of approximately `5e-324`. Values smaller than `MIN_VALUE` (“underflow values”) are converted to `0`.

It turns out that my misunderstanding came from not thinking hard enough about how floats are represented. For example, Java has the same implementation of these constants. Interestingly, C# chose to assign `MIN_VALUE` to the truly smallest value you can represent with 64-bit floats and instead created the more by-the-spec constant epsilon to determine what the smallest possible granularity you could have is.

Not what I would have expected intuitively, though I see the reasoning behind it.

Anyway, the solution we landed on for our situation was to default the bound from `Number.MIN_VALUE` to `Number.MIN_SAFE_INTEGER`. From MDN one more time:

The `Number.MIN_SAFE_INTEGER` constant represents the minimum safe integer in JavaScript (`-(2^53 - 1)`).

...

The reasoning behind that number is that JavaScript uses double-precision floating-point format numbers as specified in IEEE 754 and can only safely represent numbers between `-(2^53 - 1)` and `2^53 - 1`.

## The resulting code

``````    /**
* Given a number, decrease it by 1, or stop it at the specified min.
* @param {number} value - The value to decrease
* @param {number} min - The limit which the value can reach. Defaults to Number.MIN_VALUE.
* @returns {number} - Either value -1 or min.
*/
function decrement(value, min = Number.MIN_SAFE_INTEGER) {
const nextValue = value - 1;
return Math.max(nextValue, min);
}

decrement(10)   //      9  OK
decrement(-100) //   -101  OK
decrement(-1)   //     -2  OK
decrement(0)    //     -1  Woohoo!
``````

So, in conclusion, I still don't know JS, but I really don't know floats either. Woof.