为什么会不一致呢?
没有矛盾:这些方法只是根据不同的规范来设计。
long round(double a)
long
值。double floor(double a)
double
值。double ceil(double a)
进行比较double rint(double a)
double
值。因此,按设计round
舍入为long
,而rint
舍入为double
。自JDK 1.0以来一直如此。
JDK 1.2引入了其他一些方法(例如toRadians
,toDegrees
),1.5引入了更多方法(例如log10
,ulp
,signum
等),1.6又加入了更多方法(例如copySign
,getExponent
,nextUp
等)(请在文档中查找Since:元数据);但是round
和rint
自一开始就一直保持现在的方式。
可以说,也许不是long round
和double rint
,而是将它们命名为double round
和long rlong
更“一致”,但这是有争议的。尽管如此,如果您坚持在范畴上称之为“不一致”,那么原因可能令人不满意,就是“因为这是不可避免的”。
这里摘自《Effective Java第二版,条款40:小心设计方法签名》:
当你不确定时,请参考Java库API以获得指导。虽然存在很多不一致性 - 鉴于这些库的规模和范围,这是不可避免的 - 但也存在相当一致性。
floor()
应该返回一个double,而ceil()
应该返回一个int,那么这是否“一致”呢? - NullUserExceptionfloor
和ceil
密切相关。还有round
和rint
。我不知道你还想要什么。我试图客观地回答这个问题,进一步的推测似乎是假设性的和/或主观的。 - polygenelubricants.rint()
方法是后来添加的,以解决不一致性问题。 - NullUserExceptionMath.rint()
和Math.rlong()
分别返回int
和long
,那么当给定一个double
时,Math.round()
返回long
,而给定任何其他原始类型时返回int
,这样做会更有意义。 - supercatfloor
被选择是为了与math.h中的标准c例程匹配(另一个答案中提到的rint
也在该库中,返回一个double
,就像Java一样)。
但是,在那个时候,round
不是c的标准函数(在C89中没有提到它 - c标识符和标准;c99确实定义了round
并返回一个double
,就像你期望的那样)。语言设计者“借用”想法是很正常的,所以也许它来自其他语言?Fortran 77没有这个名称的函数,我不确定那时会使用什么作为参考。也许是vb-它确实有Round
,但对于这个理论来说不幸的是,它返回一个double
(php也是如此)。有趣的是,Perl故意避免定义round。
[更新:嗯。看起来Smalltalk返回整数。我不太了解Smalltalk是否正确和/或通用,方法称为rounded
,但它可能是源。Smalltalk在某些方面确实影响了Java(尽管更多是概念上而不是细节上)。]
如果不是Smalltalk,那么我们只能假设有人选择不当(考虑到Java中可能存在的隐式转换,似乎返回一个double
会更有用,因为这样可以在转换类型和进行浮点计算时使用)。
换句话说:Java和C共同使用的函数往往与当时的C库标准一致;其他函数似乎是任意的,但这个特定的问题可能来自Smalltalk。
我同意,Math.round(double)
返回 long
是有点奇怪的。如果将大的 double
值强制转换为 long
(这是 Math.round
隐式执行的操作),则会返回 Long.MAX_VALUE
。另一种选择是使用 Math.rint()
以避免这种情况。然而,Math.rint()
具有一种有点奇怪的舍入行为:平局按偶数整数四舍五入,即 4.5 被舍入为 4.0,但 5.5 被舍入为 6.0)。另一种选择是使用 Math.floor(x+0.5)
。但请注意,1.5 被舍入为 2,而 -1.5 被舍入为 -1,而不是 -2。还有一种选择是使用 Math.round
,但仅当数字在 Long.MIN_VALUE 和 Long.MAX_VALUE 之间时才使用。此范围外的双精度浮点值本质上是整数。
遗憾的是,我们不知道为什么Math.round()
返回long
。有人做出了这个决定,他可能从未接受采访告诉我们原因。我的猜测是,Math.round被设计为提供更好的方式(即四舍五入)将双精度转换为长整型。
和这里的其他人一样,我也不知道答案,但想着有人可能会觉得这个有用。我注意到如果你想将 double 四舍五入为 int 而不使用强制转换,可以同时使用两个 round 实现 long round(double)
和 int round(float)
:
double d = something;
int i = Math.round(Math.round(d));