【问题标题】:Why does Math.floor return a double?为什么 Math.floor 返回一个双精度值?
【发布时间】:2010-10-05 10:40:05
【问题描述】:

官方 Javadoc says Math.floor() 返回一个“等于数学整数”的 double,但是为什么不应该返回一个 int

【问题讨论】:

    标签: java math types


    【解决方案1】:

    根据同一个Javadoc:

    如果参数是NaN 或无穷大或正零或负零,则结果与参数相同。不能用int 做到这一点。

    最大的double 值也大于最大的int,所以它必须是long

    【讨论】:

    • 似乎与 Math.Round 函数不一致,后者返回 int/long 并以不同的方式处理特殊情况。
    • 注意 Javadoc 说它返回 " 最大(最接近正无穷大)*浮点值* 小于或等于参数并且等于到一个数学整数”。给定一个值 x > 2^53,它与截断小数部分的值不同。它可能比那个小很多。
    • @zod 也许他们认为人们只要愿意就可以做到(int) myFloatVar
    【解决方案2】:

    这是为了精确。双精度数据类型有一个 53 位尾数。除其他外,这意味着双精度可以表示高达 2^53 的所有整数而不会丢失精度。

    如果您将如此大的数字存储在一个整数中,您将得到溢出。整数只有 32 位。

    将整数作为双精度返回是正确的做法,因为它提供了比整数更广泛的有用数字范围。

    【讨论】:

    • 当然,它可以返回一个 long 来处理这样的值。不过,您仍然需要弄清楚如何处理大于 2^63 的双打。
    • @Jon,是的,但这会导致性能影响(我知道的任何指令集中都没有从 long 到 double 的转换指令)。我想知道 Math.floor 首先对双打 > 2^53 做了什么。有些结果无法表示。
    • 但是,也出现在官方 javadoc 中的伪惯用形式 (int)Math.floor(foo) 是不安全的,因为结果可能不适合 int,对吗?再说一次,这是一种使用 Math.floor 的安全形式,因为结果可能不适合 long?
    【解决方案3】:

    其他人已经告诉你原因,我将告诉你如何正确舍入,因为你想这样做。如果您只打算使用正数,那么您可以使用以下语句:

    int a=(int) 1.5;
    

    但是,(int) 总是向 0 舍入。因此,如果你想做一个负数:

    int a=(int) -1.5; //Equal to -1
    

    就我而言,我不想这样做。我使用以下代码进行舍入,它似乎很好地处理了所有边缘情况:

    private static long floor(double a)
    {
        return (int) Math.floor(a);
    }
    

    【讨论】:

    • 为什么不使用(int) Math.floor(a)?它可能更有效而且更短。
    • @Solomon Ucko 而不是(int) Math.floor(a),如果a 是肯定的,你可以简单地写(int) a
    【解决方案4】:

    如果你给它一个比最大的 int 或 long 大的两倍,你希望它返回什么?

    (诚然,如果它大于最大的 long 精度无论如何都会很低 - 它可能不是最接近的理论整数 - 但即便如此......)

    【讨论】:

      【解决方案5】:

      正如Java中有整数和浮点除法一样,也有整数和浮点数的取数方式:

      double f = Math.floor(x);
      

      int k = (int) x; 
      

      但您始终需要小心使用具有有限精度算术的下限:您对 x 的计算可能会产生类似 1.99999999 的结果,这两种形式都将下限为 1,而不是 2。有许多算法需要解决这个限制,以避免为某些输入值产生错误的结果。

      【讨论】:

        【解决方案6】:

        这样误差和其他非整数值可以通过一系列计算正确级联。

        例如,如果您将 Not a Number (NaN) 输入到 Math.floor,它会传递它。

        如果它返回整数,则无法传递这些状态或错误,并且您可能会从早期的计算中得到错误的结果,这些结果看起来不错,但在进一步处理后却是错误的。

        【讨论】:

          猜你喜欢
          • 2016-03-31
          • 2020-06-10
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多