Here is a sample function:
function step(x, min, max) {
return x >= min && x <= max ? x : 0;
}
console.log(step(-3 - Number.EPSILON, -3, 5)); // Expected 0, actual -3
console.log(step(5 + Number.EPSILON, -3, 5)); // Expected 0, actual 5
I need to check, that it returns zero for values outside [min, max] interval. For sure I can subtract/add a bigger number, for example 1. But I’m pretty sure, that there should exist a function returning previous/next floating point number. Could you please suggest the function or how to implement it?
>Solution :
Not all adjacent representable numbers are the same mathematical distance from one another. Floating point arcana isn’t my strong suit, but if you want to find the next representable number, I think you need to keep increasing what you add/subtract from it by Number.EPSILON for as long as you keep getting the same number.
Beware: The below is very naive
Here’s a simplistic example, but beware that it’s very naive:
function next(x) {
const ep = x < 0 ? -Number.EPSILON : Number.EPSILON;
let adder = ep;
let result;
do {
result = x + adder;
adder += ep;
} while (result === x);
return result;
}
console.log(`Next for -3: ${next(-3)}`);
console.log(`Next for 5: ${next(5)}`);
(That’s assuming direction based on the sign of the number given, which is probably not what you really want, but is easily switched up.)
An example showing how many loops are involved (including for the next representable number above Number.MAX_SAFE_INTEGER):
function next(x) {
const ep = x < 0 ? -Number.EPSILON : Number.EPSILON;
let adder = ep;
let result;
let loops = 0;
do {
result = x + adder;
adder += ep;
++loops;
if (loops % 100000 === 0) {
console.log(`loop ${loops}, adder = ${adder}`);
}
} while (result === x);
console.log(`${x} => ${result} took ${loops} loops`);
return result;
}
console.log(next(-3));
console.log(next(5));
That’s a very simplistic and naive implementation, though. A better solution could probably take a stab at the necessary amount based on the magnitude of x. For instance, if you do next(Number.MAX_SAFE_INTEGER)), this takes a very long time to come back with an answer (I’m thinking several hours). Or at least, if adding doesn’t work within X loops, consider doubling the adder repeatedly to bracket the target, then back off to close in on the correct answer. Or do bit twiddling (which definitely takes us into floating point arcana land…).