理解积分除法

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.floorMath.floor 是对double 的一个操作,当你向它提供一个 int 时它什么也不做。

返回小于或等于参数的最大值(最接近正无穷大)double 并且等于一个数学整数。特殊情况:

如果 参数值已经等于一个数学整数,那么 结果与参数相同。 如果参数是 NaN 或无穷大或正零或负零,则 结果与参数相同。

(Source)

整数除法已经具有与Math.floor 相同的逻辑行为,即它截断除法运算的其余部分。 int/int 总是返回 int

例如,100/3 将返回 3340/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,然后将其分配给一个双精度,它首先被划分为integer,然后再分配,所以你得到一个向下取整的值,转换为double

Sonar 不会因为Math.floor 而抱怨 - 它抱怨是因为您将整数除法结果(它本身是向下舍入的integer)转换为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,反向微分

《从零开始:机器学习的数学原理和算法实践》关于微积分部分的启发

《从零开始:机器学习的数学原理和算法实践》关于微积分部分的启发