反向int溢出

时间:2015-03-04 22:01:02

标签: java integer int overflow reverse

int num = -340721550;
int multi =  -214882771;
int result = num * multi; // = 10

如果我知道多重和结果,我怎么能在没有暴力强迫的情况下倒退到num?

或者提高我的强制方法的速度

public static int multiInverse(int multi, int result){
    for (int i = Integer.MIN_VALUE; i <= Integer.MAX_VALUE; i++){
        if (multi * i == result){
            return i;
        }
    }
    return -1;
}

2 个答案:

答案 0 :(得分:2)

正如在prior answer中指出的那样,可以通过计算已知除数的逆模2 ^ 32来攻击该问题。 java.math.BigInteger有一个modInverse方法可供使用。

正如在答案中指出的那样,相对于模数基数而言不是素数的数字没有逆。在二次幂的基础上,这意味着偶数也没有逆。我通过将除数和乘积减半来解决这个问题,直到除数为奇数。

不幸的是,我的所有方法都可以找到一个resultdivisor * result == product int算术 private static final BigInteger modulo = BigInteger.ONE.shiftLeft(32); public static int unoverflowDivide(int product, int divisor) { if (divisor == 0) throw new IllegalArgumentException("No solution"); while((divisor & 1) == 0){ if ((product & 1) == 1) throw new IllegalArgumentException("No solution"); divisor >>= 1; product >>= 1; } BigInteger bigDivisor = BigInteger.valueOf(divisor); BigInteger bigProduct = BigInteger.valueOf(product); BigInteger bigInverse = bigDivisor.modInverse(modulo); BigInteger bigResult = bigInverse.multiply(bigProduct); return bigResult.intValue(); } 。可能有多个此类号码,因此不一定是您开始使用的号码。

{{1}}

答案 1 :(得分:1)

简而言之,您的问题是解决以下等式:

x * b = a,其中a和b是已知的。

通常情况下,这非常简单,因为您可以这样做:

x = a / b

然而,由于我们正在使用整数,所以如果a是b的倍数,这只能给出一个合适的解决方案。例如,如果b = 2且a = 4。

如果a不是b的倍数,那么我们知道a * x导致整数溢出。

现在,想想用b划分意味着什么。你实际在做的是应用b的倒数。毕竟,b / b = 1.通过除以b,你就可以撤消b&#39;。

所以我们要做的就是找到解决方案,就是找到我们需要多个b的整数,得到这样的溢出,结果是1。

我将举一个小例子来说明这是如何运作的。

假设我们的数据类型的范围是0到8,所以它会溢出0到8之外的任何值。

在这种情况下,以下情况属实:3 * 3 == 1。 (因为9溢出到1)

现在让我们说3 * 5 == 7(因为15次溢出到7次)。

你想要的是通过知道5和7来回到3。更正式地说,你想在模块8中找到5x = 7的x。

在模块8中,5的倒数是5,因为5 * 5 = 25,溢出为1。

所以你的解决方案是7 * 5 = 3(因为35溢出到3)

但是,找到一个简单的方法来找到有符号的java整数的逆矩阵并不是那么容易。如果你甚至可以找到它,因为不是每个整数都保证有反转。