0

这是一个非常小众的问题,但我在 JS 中实现区间算术,我希望有正确的舍入。因此,我需要能够添加两个数字并将其舍入到无穷大、-infinity、零等。据我所知,JS 总是朝零舍入,并且这种行为是不可改变的,这与 C/C++ 不同狂欢节。

我怎样才能解决这个问题?如果这意味着正确的舍入,我愿意对性能产生重大影响;可能该功能可以切换以平衡速度和正确性。也许这样做的一种方法是以某种方式使函数 roundUp 和 roundDown 向上/向下舍入到下一个浮点值。

作为如何实现 roundUp/roundDown 的示例:


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...
4

1 回答 1

0

对于任何寻求快速获得连续浮点数的人来说,这很有效:

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
}

export 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
}

唯一奇怪的是它将+0-0视为相同,因此将它们四舍五入会给出最小的非规范化,并且四舍五入也是如此。

于 2022-02-01T21:08:02.550 回答