【问题标题】:Reverse Multiplication反向乘法
【发布时间】:2015-05-19 20:20:50
【问题描述】:

我有以下号码;让我们称它为第一

-1757151608

然后我有第二个号码,我们称之为未知

94507795

最后,我有了产品,我们称之为二号

-1000

如果我将表格中的前两个数字相乘,我得到的答案是 -1000。 问题是,我可以使用第一和第二,但我需要从中获得未知数。

我试过使用 BigInteger 类和它的一些函数,但没有成功。

提前致谢。

【问题讨论】:

  • “DWORD”是什么意思?一个 32 位整数,还是一个 64 位整数,还是别的什么?这可能与整数溢出有关;您需要找到未知数,这样当您将它与给定数相乘时,结果将是 -1000 整数溢出。
  • 由于操作忘记了帖子是关于 java,而不是 c++/WinAPI:DWORD 是 32 位无符号整数
  • 听起来你想将第二个乘以第一个 mod 2^32 的乘法倒数?
  • 忘记我曾经说过 dword。对数字一和未知数的乘法进行 println 的结果为 -1000,我需要向后工作,以便在知道数字一和二的同时找出未知数。
  • 数字“形式”相乘是什么意思?

标签: java math biginteger modulus


【解决方案1】:

这个乘法是不可能反转的。

首先,我们取第一个数字的二进制补码。

3904635256 = 2147483648 - -1757151608

接下来,我们将乘以第二个数字

369018468323820520 = 3904635256 * 94507795

现在,这是棘手的部分。我们将乘积转换为十六进制,并删除大于 32 位整数的数字。

51F0457800003E8 (hex) = 369018468323820520 (decimal)
800003E8 = 51F0457800003E8 moved to a 32 bit signed integer

现在,我们将十六进制值转换回十进制

2147484648 (dec) = 800003E8 (hex)

最后,我们取小数的二进制补码

-1000 = 2147483648 - 2147484648

自从我们扔掉了51F0457 (hex),我们无法找回它。这个操作的逆向是不可能的。

【讨论】:

  • 我感觉不可能,谢谢你的解释!
【解决方案2】:

我相信你想要的是将 -1000 乘以 -1757151608 模 2^32 的乘法逆元;参见,例如,the calculation in Wolfram Alpha

我编写了一个程序,我相信它可以正确地计算出你的问题的答案(如果存在)。

public class InverseMultiplication {

  // multiplicative inverse of a multiplied by b mod 2^32
  public static long invertAndMultiply(long a, long b) { 
    // take out common factors of 2
    while (a % 2 == 0 && b % 2 == 0) {
      a /= 2;
      b /= 2;
    }
    long m = 256L*256L*256L*256L; // modulus is 2^32
    long r = m;
    long nr = a;
    long t = 0;
    long nt = 1;
    while (nr != 0) {
      long q = r/nr;
      long tmp;
      tmp = nt; nt = t - q*nt; t = tmp;
      tmp = nr; nr = r - q*nr; r = tmp;
    }
    if (r > 1) throw new IllegalArgumentException(a + " has no inverse");
    t = (t*b) % m;
    while (t < Integer.MIN_VALUE) t += m;
    while (t > Integer.MAX_VALUE) t -= m;
    return t;
  }

  public static void main(String[] args) {
    long twoPow32 = 256L*256L*256L*256L;
    int n1 = -1757151608;
    int n2 = -1000;
    long unk = invertAndMultiply(n1,n2);
    System.out.println(unk);
    long pro = n1 * unk % twoPow32;
    if (pro > Integer.MAX_VALUE) pro -= twoPow32;
    System.out.println(pro);
    int pro1 = -1757151608 * 94507795;
    System.out.println(pro1);
  }
}

不过,有几点需要注意。如果你的“第一”是奇数,程序会很快找到一个独特的答案。

偶数“第一”不会有逆模 2^32,所以在这种情况下,一般情况下你会很倒霉。但是,如果您的“二号”也是偶数,您可以继续将两者除以 2(“取出 2 的公因数”),直到其中一个或两个都是奇数。希望“第一”是奇怪的,在这种情况下你会得到答案;如果“第一”即使在取出 2 的所有公因数之后,您也不会得到任何答案。在这种情况下,没有答案。

如果在偶数情况下有答案,则答案不止一个。如果你运行我的程序,你会发现它得到的答案与你的不同。

请检查一下,让我知道它是否按您期望的方式工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-03-16
    • 1970-01-01
    • 2021-07-27
    • 1970-01-01
    • 2016-07-18
    • 1970-01-01
    • 1970-01-01
    • 2020-10-29
    相关资源
    最近更新 更多