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;
}
答案 0 :(得分:2)
正如在prior answer中指出的那样,可以通过计算已知除数的逆模2 ^ 32来攻击该问题。 java.math.BigInteger有一个modInverse方法可供使用。
正如在答案中指出的那样,相对于模数基数而言不是素数的数字没有逆。在二次幂的基础上,这意味着偶数也没有逆。我通过将除数和乘积减半来解决这个问题,直到除数为奇数。
不幸的是,我的所有方法都可以找到一个result
,divisor * 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整数的逆矩阵并不是那么容易。如果你甚至可以找到它,因为不是每个整数都保证有反转。