'Rounding Modes in JavaScript
This is a pretty niche question, but I'm implementing interval arithmetic in JS and I'd like to have correct rounding. Therefore, I need to be able to add two Numbers and have it round towards infinity, -infinity, zero, etc. As far as I can tell JS always rounds towards zero and this behavior isn't changeable, unlike in C/C++ with fesetround.
How can I get around this? I'm willing to have significant performance impacts if it means correct rounding; probably the feature will be toggleable to balance speed and correctness. Perhaps one way to do this would be to somehow make functions roundUp and roundDown which round up/down to the next float value.
As an example of how roundUp/roundDown could be implemented:
const floatStore = new Float64Array(1)
const intView = new Uint32Array(floatStore.buffer)
function roundUp(x) {
if (x === Infinity)
return Infinity
if (x === -Infinity)
return -Infinity
if (isNaN(x))
return NaN
floatStore[0] = x
let leastSignificantGroup = ++intView[0]
if (leastSignificantGroup === 0)
intView[1]++
return floatStore[0]
}
(5.1).toPrecision(100) // -> 5.0999999999999996447...
roundUp(5.1).toPrecision(100) // -> 5.100000000000000532...
Solution 1:[1]
For anyone looking for a fast way to get consecutive floats, this works:
const MAGIC_ROUND_C = 1.1113332476497816e-16 // just above machine epsilon / 2
const POSITIVE_NORMAL_MIN = 2.2250738585072014e-308
const POSITIVE_DENORMAL_MIN = Number.MIN_VALUE
function roundUp (x) {
if (x >= -POSITIVE_NORMAL_MIN && x < POSITIVE_NORMAL_MIN) {
// denormal numbers
return x + POSITIVE_DENORMAL_MIN
} else if (x === -Infinity) {
// special case
return -Number.MAX_VALUE
}
return x + Math.abs(x) * MAGIC_ROUND_C
}
function roundDown (x) {
if (x > -POSITIVE_NORMAL_MIN && x <= POSITIVE_NORMAL_MIN) {
return x - POSITIVE_DENORMAL_MIN
} else if (x === Infinity) {
return Number.MAX_VALUE
}
return x - Math.abs(x) * MAGIC_ROUND_C
}
The only oddity is that it treats +0 and -0 as the same, so rounding them up both gives the minimum denormal, and same for rounding down.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
