java 为什么 Math.round 返回 long 但 Math.floor 返回 double?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3412449/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 01:43:27  来源:igfitidea点击:

Why does Math.round return a long but Math.floor return a double?

javamath

提问by Leo Jay

Why the inconsistency?

为什么不一致?

采纳答案by polygenelubricants

There is no inconsistency: the methods are simply designed to follow different specifications.

没有不一致:这些方法只是为了遵循不同的规范而设计的。

So by design roundrounds to a longand rintrounds to a double. This has always been the case since JDK 1.0.

所以按设计round舍入到 alongrint舍入到 a double。自 JDK 1.0 以来一直如此。

Other methods were added in JDK 1.2 (e.g. toRadians, toDegrees); others were added in 1.5 (e.g. log10, ulp, signum, etc), and yet some more were added in 1.6 (e.g. copySign, getExponent, nextUp, etc) (look for the Since:metadata in the documentation); but roundand rinthave always had each other the way they are now since the beginning.

JDK 1.2 中添加了其他方法(例如toRadianstoDegrees);他人在1.5中加入(例如log10ulpsignum等),并且还一些是在1.6中加入(例如copySigngetExponentnextUp等)(查找时间:在文档中的元数据); 但roundrint一直相依为命,他们现在是从一开始的方式。

Arguably, perhaps instead of long roundand double rint, it'd be more "consistent" to name them double roundand long rlong, but this is argumentative. That said, if you insist on categorically calling this an "inconsistency", then the reason may be as unsatisfying as "because it's inevitable".

可以说,也许不是long roundand double rint,将它们命名为double roundand会更“一致” long rlong,但这是有争议的。也就是说,如果您坚持明确地将其称为“不一致”,那么原因可能与“因为这是不可避免的”一样令人不满意。

Here's a quote from Effective Java 2nd Edition, Item 40: Design method signatures carefully:

这是Effective Java 2nd Edition,第 40 项:仔细设计方法签名的引述:

When in doubt, look to the Java library APIs for guidance. While there are plenty of inconsistencies -- inevitable, given the size and scope of these libraries -- there are also fair amount of consensus.

如有疑问,请查看 Java 库 API 以获得指导。尽管存在大量不一致——鉴于这些库的规模和范围,不可避免——但也有相当多的共识。

Distantly related questions

遥远的相关问题

回答by andrew cooke

floorwould have been chosen to match the standard c routine in math.h(rint, mentioned in another answer, is also present in that library, and returns a double, as in java).

floor将被选择以匹配math.h中的标准 c 例程(rint在另一个答案中提到,也存在于该库中,并返回 a double,如在 java 中)。

but roundwas not a standard function in c at that time (it's not mentioned in C89 - c identifiers and standards; c99 does define roundand it returns a double, as you would expect). it's normal for language designers to "borrow" ideas, so maybe it comes from some other language? fortran 77 doesn't have a function of that name and i am not sure what else would have been used back then as a reference. perhaps vb - that does have Roundbut, unfortunately for this theory, it returns a double(php too). interestingly, perl deliberately avoids defining round.

round当时不是 c 中的标准函数(C89 - c 标识符和标准中没有提到它;c99 确实定义了round并且它返回 a double,正如您所期望的那样)。语言设计者“借用”想法是正常的,所以它可能来自其他语言?fortran 77 没有该名称的函数,我不确定当时还会使用什么作为参考。也许 vb - 确实有,Round但不幸的是,对于这个理论,它也返回一个double(php)。有趣的是,perl故意避免定义 round

[update: hmmm. looks like smalltalk returns integers. i don't know enough about smalltalk to know if that is correct and/or general, and the method is called rounded, but it might be the source. smalltalk did influence java in some ways(although more conceptually than in details).]

[更新:嗯。看起来像smalltalk 返回 integers。我对 smalltalk 知之甚少,不知道这是否正确和/或一般,并且该方法被调用rounded,但它可能是来源。 smalltalk 确实在某些方面影响了 Java(尽管更多的是概念上的而不是细节上的)。]

if it's not smalltalk, then we're left with the hypothesis that someone simply chose poorly (given the implicit conversions possible in java it seems to me that returning a doublewould have been more useful, since then it can be used both while converting types and when doing floating point calculations).

如果不是闲聊,那么我们就会假设有人只是选择不当(考虑到 Java 中可能的隐式转换,在我看来,返回 adouble会更有用,因为它可以在转换类型和在进行浮点计算时)。

in other words: functions common to java and c tend to be consistent with the c library standard at the time; the rest seem to be arbitrary, but this particular wrinkle mayhave come from smalltalk.

换句话说:java和c通用的函数往往与当时的c库标准一致;其余的似乎是随意的,但这种特殊的皱纹可能来自闲聊。

回答by Sven

I agree, that it is odd that Math.round(double)returns long. If large doublevalues are cast to long(which is what Math.roundimplicitly does), Long.MAX_VALUEis returned. An alternative is using Math.rint()in order to avoid that. However, Math.rint()has a somewhat strange rounding behavior: ties are settled by rounding to the even integer, i.e. 4.5 is rounded down to 4.0 but 5.5 is rounded up to 6.0). Another alternative is to use Math.floor(x+0.5). But be aware that 1.5 is rounded to 2 while -1.5 is rounded to -1, not -2. Yet another alternative is to use Math.round, but only if the number is in the range between Long.MIN_VALUE and Long.MAX_VALUE. Double precision floating point values outside this range are integers anyhow.

我同意,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 之间的范围内。无论如何,超出此范围的双精度浮点值都是整数。

Unfortunately, why Math.round()returns longis unknown. Somebody made that decision, and he probably never gave an interview to tell us why. My guess is, that Math.round was designed to provide a better way (i.e., with rounding) for converting doubles to longs.

不幸的是,为什么Math.round()返回long是未知的。有人做出了那个决定,他可能从未接受采访告诉我们原因。我的猜测是, Math.round 旨在提供一种更好的方法(即舍入)将双精度转换为长整数。

回答by Dovev Hefetz

Like everyone else here I also don't know the answer, but thought someone might find this useful. I noticed that if you want to round a double to an int without casting, you can use the two round implementations long round(double)and int round(float)together:

像这里的其他人一样,我也不知道答案,但我认为有人可能会觉得这很有用。我注意到,如果你想圆一个双为int没有铸造,可以使用两度回合的实现long round(double)int round(float)在一起:

double d = something;
int i = Math.round(Math.round(d));