【问题标题】:How can you calculate a factor if you have the other factor and the product with overflows?如果你有另一个因子和溢出的产品,你如何计算一个因子?
【发布时间】:2016-07-31 23:49:58
【问题描述】:
a * x = b

我有一个看似相当复杂的乘法/imul 问题:如果我有 a 和我有 b,如果它们都是 32 位双字,我如何计算 x(例如 0-1 = FFFFFFFF,FFFFFFFF+1 = 0 )? 例如:

0xcb9102df * x = 0x4d243a5d

在这种情况下,x 是 0x1908c643。我发现了一个类似的问题,但前提不同,我希望有一个比给出的更简单的解决方案。

【问题讨论】:

  • 分成大小,做4次乘法和加法。 (L1+S1)*(L2+S2)
  • 这可能并不总是有一个唯一的解决方案,我不确定。我的第一个想法是找到multiplicative inverse,这是编译器将除法转换为乘法的方式,这对于像 32 位整数这样的模块化类型是可能的。 gcc just generates code that return 0 or 1 用于除以 0xcb9102df,当然。 (除以小整数时存在乘法逆元,例如我在那个godbolt链接中包含的 div13 函数)。
  • 我有这个等式(十进制)4*x=?2, ?是溢出的数字。我可以恢复 x 吗?

标签: c++ c x86 dword


【解决方案1】:

如果它们是奇数,则数字具有模乘逆模,恰好是 2 的幂。其他一切都是位移奇数(即使是零,可能是任何东西,所有位都移出)。所以有几种情况:

给定a * x = b

  • tzcnt(a) > tzcnt(b)无解
  • tzcnt(a) <= tzcnt(b) 可解,有 2tzcnt(a)

第二种情况有一个特殊情况,有1个解,奇数a,即x = inverse(a) * b

更一般地说,x = inverse(a >> tzcnt(a)) * (b >> tzcnt(a)) 是一个解决方案,因为您将a 写为(a >> tzcnt(a)) * (1 << tzcnt(a)),所以我们用它的逆来取消左因子,我们将右因子作为结果的一部分(无论如何都不能取消)然后乘以剩余的值以达到b。显然,仍然只适用于第二种情况。如果您愿意,您可以通过填写顶部tzcnt(a) 位的所有可能性来枚举所有解决方案。

剩下的唯一一件事就是得到逆,你可能已经在另一个答案中看到它,不管它是什么,但为了完整起见,你可以按如下方式计算它:(未测试)

; input x
dword y = (x * x) + x - 1;
dword t = y * x;
y *= 2 - t;
t = y * x;
y *= 2 - t;
t = y * x;
y *= 2 - t;
; result y

【讨论】:

  • 非常感谢!它有效,这正是我想要的。不过,我并不完全理解。与其要求你解释一个巨大的主题,你可以向我推荐一个我可以用谷歌搜索的一般主题/一本书吗?谢谢!
  • (如果美国系统适用,我目前在 Alg 2)
  • @Lupe 好吧,问题出在哪里?
  • @Lupe 好吧,我不知道该告诉你什么,他们可能会在 Alg 2 中介绍这一点,也许不会。无论哪种方式,奇数的乘法逆元模2的幂的存在都来自2的幂和奇数为1之间的gcd和Bézout的恒等式。它还非常直观地遵循了一种构造它们的方法:从 1 开始构建逆,然后查看需要抵消的最低位,添加 2 的相关幂等。逆算法有一个牛顿法的应用。我猜其余的很明显?
  • @harold:没错,它是用乘法代替除法,而不是使用乘法作为另一个乘法的逆。我是说我以前没有听说过后者,但我认为这和这之间可能存在某种关系,或者至少它是另一个有趣的工具,即使你并不真正了解数学。 (我想当我需要自己实现它时,我会阅读更多并理解它。在那之前,我很高兴知道它存在)。感谢您对寻找倒数的总结,尤其是。确认这些是牛顿迭代
猜你喜欢
  • 2020-07-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多