如何检测和防止整数溢出时乘以浮点数在Java中的整数?



我已经阅读了这篇文章NUM00-J。检测或防止整数溢出和这个问题Java如何处理整数下溢和溢出以及如何检查它?

可以看到,当一个整数乘以另一个整数时,有许多解决方案可以防止整数溢出。但我想知道是否有任何解决方案,以防止整数溢出时乘以浮点数?

我当前的(愚蠢的)解决方案:

public static final int mulInt(int a, float b) {
double c = a * b;
return c > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)c;
}

但是它有很多问题:

  1. 执行乘法运算可以得到预期的结果两个参数都必须是小数值的乘法。
  2. 当参数是大型数字结果是必然不正确(我知道部分原因是因为浮点数据类型)。
  3. 假设如果计算结果大于最大值加倍,它将不可阻挡地返回a负数。

那么,这个问题的真正解决方案是什么呢?

你的回答会很有帮助,我会很感激的!

更新:这里有另一个问题,我如何检查两个数字在Java中相乘是否会导致溢出?这是非常相似的,但它是用一个整数乘以一个整数,而不是乘以一个浮点数。

下面是一个可能对Java有启发的C方法。

在赋值前使用double而不是floatmath执行乘法运算,以获得double的额外精度/范围。

c > Integer.MAX_VALUE这样的比较,Integer.MAX_VALUE首先被转换成double。这可能会失去精确性。*1考虑如果转换值是Integer.MAX_VALUE + 1.0会发生什么。然后,如果cInteger.MAX_VALUE + 1.0,代码将尝试返回(int) (Integer.MAX_VALUE + 1.0)-不好。最好使用格式良好的极限。(也有负面的。)在C语言(可能是Java)中,到int的浮点转换会截断分数。在边缘处需要特别小心。

#define INT_MAX_PLUS1_AS_DOUBLE ((INT_MAX/2 + 1)*2.0)
int mulInt(int a, float b) {
// double c = a * b;
double c = (double) a * b;

//return c > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int)c;
if (c < INT_MAX_PLUS1_AS_DOUBLE && c - INT_MIN > -1.0) {
return (int) c;
} 
if (c > 0) return INT_MAX;
if (c < 0) return INT_MIN;
return 0; // `b` was a NaN
}

c - INT_MIN > -1类似于c > INT_MIN - 1,但由于INT_MIN是-2的幂,INT_MIN - 1可能不能精确地转换为doublec - INT_MIN应该精确地接近边缘情况。


*1int为32位(或更少)而double为64位(具有53位有效)时没有问题。但重要的与更大范围的整数类型。

最新更新