JavaScript Math.floor:保证号码将如何舍入?

时间:2013-05-31 22:12:00

标签: javascript math floor

我想规范化一个数组,使每个值都在[0-1]中..即,最大值永远不会是1,但min可以是0.这与返回相同范围内的数字的随机函数不同。

看着这个,我发现.99999999999999999 === 1是真的! Ditto(1-Number.MIN_VALUE)=== 1但是Math.ceil(Number.MIN_VALUE)应该是1。 其他一些:Math.floor(.999999999999)为0而Math.floor(.99999999999999999)为1

好的,所以JS中存在舍入问题。

有什么方法可以将一组数字归一化到[0,1]范围内?

3 个答案:

答案 0 :(得分:2)

检查JavaScript对每个表达式执行的步骤可能会有所帮助。

.99999999999999999===1

  1. 源文本.99999999999999999将转换为数字。最接近的数字是1,因此这是结果。 (下一个最接近的数字是0.99999999999999988897769753748434595763683319091796875,这是1-2 -53 。)
  2. 然后将1与1进行比较。结果为真。
  3. (1-Number.MIN_VALUE) === 1

    1. Number.MIN_VALUE是2 -1074 ,约5e-304。
    2. 1-2 -1074 非常接近一个。确切的值不能表示为数字,因此使用最接近的值。同样,最近的值为1.
    3. 然后将1与1进行比较。结果为真。
    4. Math.ceil(Number.MIN_VALUE)

      1. Number.MIN_VALUE是2 -1074 ,约5e-304。
      2. 该值的上限函数为1.
      3. Math.floor(.999999999999)

        1. 源文本.999999999999将转换为数字。最接近的数字是0.99999999999900002212172012150404043495655059814453125,这就是结果。
        2. 该值的楼层功能为0.
        3. Math.floor(.99999999999999999)

          1. 源文本.99999999999999999将转换为数字。最接近的数字是1,因此这就是结果。
          2. 1的楼层功能是1.
          3. 这里最多只有两件令人惊讶的事情。一个是源文本中的数字被转换为内部数字值。但这不应该令人惊讶。当然,文本必须转换为数字的内部表示,而数字类型不能完美地存储所有无限多个数字。所以它必须圆。当然,数字非常接近1轮到1。

            另一个可能令人惊讶的事情是1-Number.MIN_VALUE是1.但这实际上是同一个问题:确切的结果是不可表示的,但它非常接近1,因此使用1。

            Math.floor功能正常运行。它从不会引入任何错误,您无需做任何事情来保证它会向下舍入。它总是这样。

            但是,由于您想要对数字进行标准化,因此您似乎可能会在某个时刻对数字进行分割。除法时,可能存在舍入问题,因为除法的许多结果不完全可以表示,因此必须舍入。

            但是,这是一个单独的问题,并且您没有在此问题中提供足够的信息来解决您计划执行的具体计算。你应该为它开一个单独的问题。

答案 1 :(得分:0)

请理解一件事:这......

.999999999999999999

...只是一个数字文字。就像

一样
.999999999999999998
.999999999999999997
.999999999999999996
...

......你看到了模式。

JavaScript如何处理这些文字完全是另一回事。是的,此处理受限于可用于存储Number 的位数。

根据定义,可能的浮点文字数量是无限的 - 无论为它们设置的范围有多小。例如,如上所示:您可以表达多少numbers very close to 1?是的,它是无限的:只需将9附加到该行。

但是每个Number值的容器是非常有限的:它有64位。这意味着,它可以存储2 ^ 64个不同的值(其中Infinite-InfiniteNaN) - 这就是全部。

你想要使用这样的文字吗?使用字符串存储它们,而不是数字 - 以及一些BigMath JS库(take your pick)来处理这些值 - 再次作为字符串。

但是从你的问题看起来你不是,因为你谈到Numbers - 数字的数组,就是这样。并且绝不会存储.999999999999999999,因为JavaScript中没有此类

答案 2 :(得分:0)

Javascript会将0.999999999999999994和1之间的任意数字视为1,因此只需减去.000000000000000006。

当然这并不像听起来那么容易,因为.000000000000000006在Javascript中被评估为0,所以你可以这样做:

function trueFloor(x)
{
    x = x * 100;
    if(x > .0000000000000006)
        x = x - .0000000000000006;
    x = Math.floor(x/100);
    return x;
}

编辑:或者至少你认为你可以。显然JS在将它传递给函数之前将.99999999999999999转换为1,所以你必须尝试类似的东西:

trueFloor("0.99999999999999999")

function trueFloor(str)
{
    x=str.substring(0,9) + 0;
    return Math.floor(x); //=> 0
}

不确定为什么你需要那么高的精度,但从理论上讲,我认为它有效。你可以看到一个工作小提琴here

只要您将精确的float投射为string,这可能是您最好的选择。