为啥 Math.floor 返回一个双精度值?

Posted

技术标签:

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

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

【问题讨论】:

【参考方案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,它会传递它。

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

【讨论】:

以上是关于为啥 Math.floor 返回一个双精度值?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这些双精度数的返回值是 -1.#IND?

Math.floor是啥?

java math.floor是啥意思

Math对象(min()-max()-ceil()-floor()-round()和abs())

Math 类

js的math