为什么Math.floor返回一个双精度浮点数?

122

官方Javadoc 表示Math.floor() 返回一个“等于数学整数”的double,但为什么它不返回一个int呢?

6个回答

87

根据同样的Javadoc:

如果参数是NaN、无穷大或正零或负零,则结果与参数相同。使用int无法实现这一点。

最大的double值也比最大的int值更大,因此必须使用long


49
似乎与Math.Round函数不一致,后者返回int/long并以不同的方式处理特殊情况。 - zod
1
请注意Javadoc中所说的返回值是“最大(接近正无穷大)小于或等于参数且等于数学整数的浮点值”。给定一个值_x > 2^53_,它与其小数部分截断后的值不同。它可能比那个值小得多。 - Jim Garrison
1
@zod 或许他们认为人们可以通过(int) myFloatVar来实现。 - Sujit
一个双精度数如何变成NAN呢? - Philip Rego

20

这是为了精度。双精度数据类型具有53位尾数。这意味着,不会丢失精度的情况下,双精度可以表示所有小于2^53的整数。

如果您将这样一个大数存储为整数,则会发生溢出。整数只有32位。

在此处将整数返回为双精度浮点值是正确的,因为它提供了比整数更广泛和有用的数字范围。


1
当然,它可以返回一个长整型来处理这样的值。但是,你仍然需要想出如何处理大于2^63的双精度数。 - Jon Skeet
1
@Jon,没错,但这会导致性能下降(据我所知,任何指令集中都没有从long到double的转换指令)。我想知道Math.floor在第一次使用大于2^53的双精度数时会发生什么。有些结果是无法表示的。 - Nils Pipenbrinck
1
但是,伪惯用形式(int)Math.floor(foo),它也出现在官方的javadoc中,是不安全的,因为结果可能无法适应int,我是对的吗?那么,哪种形式是使用Math.floor的安全形式,因为结果甚至可能无法适应long? - Raibaz

17

其他人已经告诉你为什么要这样做,我将告诉你如何正确地四舍五入。如果你只需要使用正数,那么可以使用以下语句:

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);
}

7
为什么不使用(int) Math.floor(a)呢?这可能更有效率也更简短。 - Solomon Ucko
1
@Solomon Ucko,如果a是正数,你可以直接写(int) a,而不是写成(int) Math.floor(a)。 - Lev Leontev

3
如果您输入一个大于最大int或long的double,它会返回什么呢?(即使它比最大的long还要大,精度也会很低 - 它可能不是最近的理论整数 - 但即便如此......)

1
正如Java中存在整数和浮点数除法一样,计算floor的方法也有整数和浮点数两种方式:
double f = Math.floor(x);

或者

int k = (int) x; 

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


0
为了让错误和其他非整数值能够正确地通过一系列计算。
例如,如果你将非数字(NaN)输入Math.floor中,它会将其传递下去。
如果它返回整数,它就无法传递这些状态或错误,你可能会从早期计算中得到看起来不错但在进一步处理后是错误的结果。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接