理解积分除法
Posted
技术标签:
【中文标题】理解积分除法【英文标题】:Understanding integral division 【发布时间】:2014-10-07 14:39:18 【问题描述】:我有以下代码:
public static final long KILOMETER_IN_METERS = 1000;
public static int getKilometers(int distanceInMeter)
return (int) Math.floor(distanceInMeter / KILOMETER_IN_METERS);
对于带有 return 语句的行,Sonar 说:
积分除法结果转换为双精度或浮点数Here is the full description of this bug.
据我了解,它说存在 int/int 除法,其结果可能是 浮点值,但我可能错了。 我该如何正确处理这种情况?
【问题讨论】:
【参考方案1】:这里不需要使用Math.floor
。 Math.floor
是对double
的一个操作,当你向它提供一个 int 时它什么也不做。
返回小于或等于参数的最大值(最接近正无穷大)
如果 参数值已经等于一个数学整数,那么 结果与参数相同。 如果参数是 NaN 或无穷大或正零或负零,则 结果与参数相同。double
并且等于一个数学整数。特殊情况:
(Source)
整数除法已经具有与Math.floor
相同的逻辑行为,即它截断除法运算的其余部分。 int/int
总是返回 int
。
例如,100/3
将返回 33
,40/50
将返回 0
。
只需使用此代码:
public static int getKilometers(int distanceInMeter)
return distanceInMeter / KILOMETER_IN_METERS;
【讨论】:
哈,你扩展了你的答案,而我正在扩展你的答案。 :) 谢谢 Eran,但我有 long 类型的常量,在return distanceInMeter / KILOMETER_IN_METERS;
的结果中我有异常,因为预期为 int,但很早就找到了。
@josser 好吧,没有理由让你的常量很长,因为它的值非常小。如果它必须很长,则需要强制转换为 int。
是的,你是对的——只要是一个整数就足够了。至于 Math.floor - 似乎没有必要在这里使用它。谢谢。【参考方案2】:
那是因为Math.floor
将 double 作为参数,而整数除以整数已经是整数。所以所有关于声纳的投射声纳都在那里完成,而不是在你对int
的显式投射上。
这是floor
的文档:http://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#floor%28double%29
【讨论】:
【参考方案3】:为了扩展 Eran 的答案,这就是你正在做的事情:
distanceInMeter / KILOMETER_IN_METERS
将整数除以整数。在 Java 中,该结果是一个截断的整数。然后你把它放入Math.floor
,它需要一个双倍。因此,Java 试图通过将您的 int
变成 double
来帮助您。然后你将Math.floor
返回的double
转换回int
。
如果您一直在关注,您可能已经注意到您已经有了截断的 int。所以你的代码需要很简单:
public static int getKilometers(int distanceInMeter)
return distanceInMeter / KILOMETER_IN_METERS;
【讨论】:
该代码无法编译,KILOMETER_IN_METERS 很长。您需要先将其转换为 int。【参考方案4】:当你将两个整数相除时,你总是会得到一个整数,向下取整。
如果你划分distanceInMeter / KILOMETER_IN_METERS
,然后将其分配给一个双精度,它首先被划分为int
eger,然后再分配,所以你得到一个向下取整的值,转换为double
。
Sonar 不会因为Math.floor
而抱怨 - 它抱怨是因为您将整数除法结果(它本身是向下舍入的int
eger)转换为double
。大多数情况下,这是一个错误(为什么故意自动循环并在之后立即转换为双精度)?
int distanceInMeter = 505;
double result = distanceInMeter / KILOMETER_IN_METERS;
System.out.println(result); // 0.0
double result2 = distanceInMeter * 1.0 / KILOMETER_IN_METERS;
System.out.println(result2); // 0.505
double result3 = ((double) distanceInMeter) / KILOMETER_IN_METERS;
System.out.println(result3); // 0.505
1.0 * distanceInMeter / KILOMETER_IN_METERS
((double)distanceInMeter) / KILOMETER_IN_METERS
【讨论】:
以上是关于理解积分除法的主要内容,如果未能解决你的问题,请参考以下文章
三十分钟理解计算图上的微积分:Backpropagation,反向微分