【问题标题】:Arbitrary-precision integer division, how to deal with 32-bit remainders?任意精度整数除法,如何处理 32 位余数?
【发布时间】:2019-05-19 19:34:40
【问题描述】:

我需要将一个数字 N 除以另一个数字 D,两者都大于我的 32 位字长

目前我正在使用此处找到的算法: http://justinparrtech.com/JustinParr-Tech/an-algorithm-for-arbitrary-precision-integer-division/

我正在为 RISC-V ISA 实施我的解决方案

但是在第三步Q = N / A的时候,如果余数也是32位数字我不知道该怎么办,因为通常我会用这个余数来除下一个单词但是如果这是寄存器的大小,不可能考虑到它。

我一直在考虑如何解决这个问题,但我想出的每一个解决方案我都觉得这不是最好的方法。

【问题讨论】:

  • 在该页面上的示例中,看起来他们没有保留该步骤的其余部分。另请记住,您通常使用基数 2^32 或基数 10^9,因此每个 32 位整数都是一个“数字”。实际上使用 10 进制数字是非常低效的。
  • 但要使其工作,您需要 64 位 / 32 位 => 32 位除法指令。 (许多 32 位 ISA 提供了这一点)。否则你必须使用 32-bit / 32-bit => 32-bit 来做 16-bit 块。

标签: assembly 32-bit bigint riscv


【解决方案1】:

那个算法太可怕了。

第一步应该是确定结果的符号(从分子和除数的符号);然后找到分子和除数的大小(并为“分子为 0”和“abs(divisor) 为 0 或 1”的情况提供快捷方式,其中实际进行除法是可以避免或不可能的),以便执行代码实际的除法只处理正数。

第二步应该是确定除数是否足够小以容纳单个数字(无论数字是您的语言/环境支持的最大基数 - 例如对于具有 32 位整数的 C,它可能是“base 65536”,对于 64 位 80x86 汇编语言(可以使用 128 位分子),它可能是“base 18446744073709551616”)。此时,您将分支到 2 个完全不同的算法之一。

小除数

这是一个相对简单的“对于分子中的每个数字 { 除数除以找到结果中的数字}”循环(然后修复您在开始时确定的结果的符号)。

大除数

为此,我将使用二进制除法。这个想法是左/右移动分子和除数,以便除数变得尽可能大而不大于分子。然后从分子中减去除数,并在结果中设置与左/右移动量相对应的位;并重复此操作,以便(在初始移位之后)它最终成为“将分子的剩余部分向左移动;然后与除数比较,如果分子大于除数,则从分子中减去除数并在结果中设置位”在循环中当分子没有剩余时终止)。

题外话

对于大多数需要任意精度除法的情况;最好使用有理数,其中每个数字都存储为三个(任意大小)整数——分子、除数和指数(如number = numerator/divisor * (1 << exponent))。在这种情况下,您永远不需要除 - 您只需乘以倒数。这使其性能更好,但精度也显着提高(例如,您可以计算 (1/3) * 6 并保证不会有精度损失)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-04-25
    • 1970-01-01
    • 2014-01-28
    • 2014-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多