Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java:使用assert实现长类型溢出免疫_Java_Jvm_Assert_Assertions - Fatal编程技术网

Java:使用assert实现长类型溢出免疫

Java:使用assert实现长类型溢出免疫,java,jvm,assert,assertions,Java,Jvm,Assert,Assertions,这是我计算有理数不同运算的代码。现在,我的任务是使用assert实现额外的安全性,以防止溢出。我试图做一些事情,但当我向JVM启用带有-ea的断言时,它开始一直“抛出”断言(即使是4>5assert条件)我如何实现这一点,以及在长数字上实现这一点的正确方法是什么? public class Rational { private final long numerator; private final long denominator; private double result; public

这是我计算有理数不同运算的代码。现在,我的任务是使用
assert
实现额外的安全性,以防止溢出。我试图做一些事情,但当我向JVM启用带有
-ea
的断言时,它开始一直“抛出”断言(即使是
4>5
assert条件)我如何实现这一点,以及在
数字上实现这一点的正确方法是什么?

public class Rational {

private final long numerator;
private final long denominator;
private double result;

public Rational(long numerator, long denominator){
    this.numerator = numerator;
    this.denominator = denominator;
    result = (double)numerator/(double)denominator;
}

public Rational plus(Rational b){
    assert this.denominator * b.denominator >= Long.MAX_VALUE : "Overflow of denominator in 'PLUS'"; //My attempt

    long plusDenominator = this.denominator * b.denominator;
    long plusNumerator = ((plusDenominator / this.denominator) * this.numerator) + ((plusDenominator / b.denominator) * b.numerator);
    long gcd = gcd(plusNumerator, plusDenominator);
    return new Rational(plusNumerator / gcd, plusDenominator / gcd);
}

public Rational minus(Rational b){
    long minusDenominator = this.denominator * b.denominator;
    long minusNumerator = ((minusDenominator / this.denominator) * this.numerator) - ((minusDenominator / b.denominator) * b.numerator);
    long gcd = gcd(minusNumerator, minusDenominator);
    return new Rational(minusNumerator / gcd, minusDenominator / gcd);
}

public Rational times(Rational b){
    long timesDenominator = this.denominator * b.denominator;
    long timesNumerator = this.numerator * b.numerator;

    long gcd = gcd(timesDenominator, timesNumerator);
    return new Rational(timesNumerator / gcd, timesDenominator / gcd);
}

public Rational divides(Rational b){
    long divDenominator = this.denominator * b.numerator;
    long divNumerator = this.numerator * b.denominator;

    long gcd = gcd(divNumerator, divDenominator);
    return new Rational(divNumerator / gcd, divDenominator / gcd);
}

private long gcd(long p, long q){
    if(q == 0) return p;
    long r = p % q;
    return gcd(q, r);
}

public static void main(String[] args){
    Rational r1 = new Rational(8, 999999999999999999L);
    Rational r2 = new Rational(8 ,999999999999999999L);
    System.out.println(r1.plus(r2));
}

}测试如下:

assert this.denominator * b.denominator >= Long.MAX_VALUE . . .
不可能是对的。如果
this.denominor*b.denominor
溢出,则结果可能为负值;它当然不能大于
Long.MAX_值
,并且几乎不可能等于
Long.MAX_值
。您需要一种更有效的方法来检测溢出是否会发生

通常的方法是向上投射到更大的整数大小,或者进行预测试。由于您已经在使用
long
,因此唯一可用的向上转换是
biginger
,我假设您不想使用它。以下是如何使用预测试:

static final long safeMultiply(long left, long right)
                 throws ArithmeticException {
  if (right > 0
         ? left > Long.MAX_VALUE/right || left < Long.MIN_VALUE/right 
         : (right < -1
             ? left > Long.MIN_VALUE/right  || left < Long.MAX_VALUE/right
             : right == -1 && left == Long.MIN_VALUE) ) {
      throw new ArithmeticException("Long overflow");
  }
  return left * right;
}
static final long safeMultiply(左长、右长)
抛出算术异常{
如果(右)大于0
?左>长.MAX_值/右| |左<长.MIN_值/右
:(右<-1
?左>长.MIN_值/右| |左<长.MAX_值/右
:right==-1&&left==Long.MIN\u值){
抛出新的算术异常(“长溢出”);
}
返回左*右;
}

我不建议对此使用
assert
,因为它可以在运行时关闭。您可以在某个地方维护一个标志,指示是否发出溢出信号,如果该标志为
false

,则跳过测试,即使在4>5个条件下也是如此
assert condition
表示您希望
condition
为true,如果
condition
false
(),则程序必须结束。毫无疑问,
4>5
会触发它。如果第三方库是公平的游戏,那么Guava是一种优化的乘法和检查溢出方法。