任意精度整数除法,32位余数如何处理?
Arbitrary-precision integer division, how to deal with 32-bit remainders?
我需要将一个数字 N 除以另一个数字 D,两者都大于我的 32 位字长
目前我正在使用在这里找到的算法:
http://justinparrtech.com/JustinParr-Tech/an-algorithm-for-arbitrary-precision-integer-division/
我正在为 RISC-V ISA 实施我的解决方案
但是在第三步Q = N / A
的时候,如果余数也是32位的数,我不知道该怎么办,因为通常我会用这个余数来除法下一个单词,但如果它是寄存器的大小,则不可能将其考虑在内。
我一直在思考如何解决这个问题,但我觉得我想出的每一个解决方案都不是最好的方法。
那个算法太可怕了。
第一步应该是确定结果的符号(从分子和除数的符号);然后找到分子和除数的大小(并且 short-cuts 对于 "numerator is 0" 和 "abs(divisor) is 0 or 1" 实际进行除法是可以避免或不可能的情况)以便执行实际除法的代码只处理正数。
第二步应该是确定除数是否小到足以容纳一个数字(数字位于您的 language/environment 支持的最大基数中 - 例如,对于具有 32- 的 C位整数可能是 "base 65536",对于 64 位 80x86 汇编语言(您可以在其中使用 128 位分子),它可能是 "base 18446744073709551616")。此时您分支到 2 种完全不同的算法之一。
小除数
这是一个相对简单的 "for each digit in numerator { divide digit by divisor to find the digit in the result}" 循环(然后修正您在开始时确定的结果的符号)。
大除数
为此,我将使用二进制除法。这个想法是移动分子和除数 left/right 以便除数在不大于分子的情况下变得尽可能大。然后你从分子中减去除数并在结果中设置对应于你移动了多少的位 left/right;并重复此操作,以便(在初始移位之后)它最终成为 "shift whatever remains of the numerator left; then compare to divisor, and if numerator is larger than divisor subtract divisor from numerator and set bit in result" 在一个循环中,该循环在分子没有剩余时终止)。
Off-Topic备选
对于大多数需要arbitrary-precision除法的情况;最好使用有理数,其中每个数字存储为三个(任意大小的)整数 - 分子、除数和指数(如 number = numerator/divisor * (1 << exponent)
)。在这种情况下,您永远不需要除法——只需乘以倒数即可。这使得它的性能更好,但精度也明显更好(例如,您可以计算 (1/3) * 6
并保证不会有精度损失)。
我需要将一个数字 N 除以另一个数字 D,两者都大于我的 32 位字长
目前我正在使用在这里找到的算法: http://justinparrtech.com/JustinParr-Tech/an-algorithm-for-arbitrary-precision-integer-division/
我正在为 RISC-V ISA 实施我的解决方案
但是在第三步Q = N / A
的时候,如果余数也是32位的数,我不知道该怎么办,因为通常我会用这个余数来除法下一个单词,但如果它是寄存器的大小,则不可能将其考虑在内。
我一直在思考如何解决这个问题,但我觉得我想出的每一个解决方案都不是最好的方法。
那个算法太可怕了。
第一步应该是确定结果的符号(从分子和除数的符号);然后找到分子和除数的大小(并且 short-cuts 对于 "numerator is 0" 和 "abs(divisor) is 0 or 1" 实际进行除法是可以避免或不可能的情况)以便执行实际除法的代码只处理正数。
第二步应该是确定除数是否小到足以容纳一个数字(数字位于您的 language/environment 支持的最大基数中 - 例如,对于具有 32- 的 C位整数可能是 "base 65536",对于 64 位 80x86 汇编语言(您可以在其中使用 128 位分子),它可能是 "base 18446744073709551616")。此时您分支到 2 种完全不同的算法之一。
小除数
这是一个相对简单的 "for each digit in numerator { divide digit by divisor to find the digit in the result}" 循环(然后修正您在开始时确定的结果的符号)。
大除数
为此,我将使用二进制除法。这个想法是移动分子和除数 left/right 以便除数在不大于分子的情况下变得尽可能大。然后你从分子中减去除数并在结果中设置对应于你移动了多少的位 left/right;并重复此操作,以便(在初始移位之后)它最终成为 "shift whatever remains of the numerator left; then compare to divisor, and if numerator is larger than divisor subtract divisor from numerator and set bit in result" 在一个循环中,该循环在分子没有剩余时终止)。
Off-Topic备选
对于大多数需要arbitrary-precision除法的情况;最好使用有理数,其中每个数字存储为三个(任意大小的)整数 - 分子、除数和指数(如 number = numerator/divisor * (1 << exponent)
)。在这种情况下,您永远不需要除法——只需乘以倒数即可。这使得它的性能更好,但精度也明显更好(例如,您可以计算 (1/3) * 6
并保证不会有精度损失)。