Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to get closest floating point number that is less/greater than a given number

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?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>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…).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading