【发布时间】:2016-01-06 06:15:15
【问题描述】:
过去几天我一直在研究这个问题,但我无法找到答案。如果除数只有一个词,我想出了一种有效的算法。但是,如果除数是多个单词,那么我会得到一些奇怪的答案。我知道这个问题已经在这里被问过几次了,但是除了使用教科书的方法或者去买一本关于这个主题的书外,没有明确的答案。我已经能够让我的大整数库中的每个函数都可以工作,除了除法。似乎有些人认为大整数除法是一个 NP 难题,并且由于我遇到的麻烦,我倾向于同意。
数据存储在一个结构中,该结构包含指向 uint16_t 或 uint32_t 数组的指针,具体取决于是否支持 long long 数据类型。如果不支持 long long,则 uint16_t 用于从乘法和加法运算中捕获任何进位/溢出。我目前拥有的功能是加法、减法、乘法、2 的补码求反、比较和、或、异或、非、左移、右移、左旋转、右旋转、位反转(反射)、一些转换例程,一个随机数填充例程,以及其他一些实用例程。除除法外,所有这些都正常工作(我在计算器上检查了结果)。
typedef struct bn_data_t bn_t;
struct bn_data_t
{
uint32 sz1; /* Bit Size */
uint32 sz8; /* Byte Size */
uint32 szw; /* Word Count */
bnint *dat; /* Data Array */
uint32 flags; /* Operational Flags */
};
这与我问过的关于 inline assembler 的另一个问题有关,因为这就是它的用途。
到目前为止我发现了什么:
Algorithm for dividing very large numbers
What is the fastest algorithm for division of crazy large integers?
https://en.wikipedia.org/wiki/Division_algorithm
Newton-Raphson Division With Big Integers
还有一堆关于这个主题的学术论文。
到目前为止我所做的尝试:
我有一个基本的例程工作,但它将一个多字大整数除以一个字。我试图实现一个 Newton-Raphson 算法,但这不起作用,因为我得到了一些非常奇怪的结果。我从微积分中了解牛顿的方法,但这是整数数学而不是浮点数。我了解 Goldschmidt 除法算法背后的数学,但我不清楚如何用整数数学来实现它。其中一些算法的部分问题是它们需要以 2 为底的对数函数。我知道如何使用浮点数和泰勒级数实现对数函数,但在使用整数数学时不知道。
我曾尝试查看GMP 库,但除法算法的文档记录不是很好,这让我有点不知所措。似乎他们在不同的点使用了不同的算法,这增加了混乱。
对于学术论文,我大部分理解数学(我已经清除了基本微积分数学、多变量微积分和常微分方程),但我的数学和数学之间又一次脱节了使用整数数学的知识和实现。我已经看到建议的小学方法,据我所知,它类似于移位减法,但我也不太确定如何实现该方法。有任何想法吗?代码会很好。
编辑:
这是我个人的学习经历。我想了解它是如何完成的。
编辑:2016 年 6 月 4 日
我已经有一段时间没有做这个了,因为我还有其他的熨斗和其他项目要处理。现在我重新审视了这个项目,我终于使用两种不同的算法实现了大整数除法。基本的一种是here 概述的移位减法。使用 CPU 除数指令的高速算法只有在除数为一个字时才被调用。两种算法都已确认可以正常工作,因为它们产生的结果已通过online big number calculator 进行了检查。所以现在,所有基本的数学和逻辑功能都已经实现了。这些功能包括加法、减法、乘法、除法、模除法、模数和、或非、异或、取反、反转(反射)、左移、右移、左旋转和右旋转。我可能会在他们需要时添加其他功能。感谢所有回复的人。
【问题讨论】:
-
这不是特定于语言的。基本上,您应该考虑一下您在学校是如何使用笔和纸学习除法的。
-
认为大整数包含以 2**n 为底的数字,而不是以 2 或 10 为底的数字。这有时被称为“高基数”方法。在您的情况下,这些数字似乎存储在数组
dat中。如果您像在小学时所学的那样从手除法开始,那么您的工作将有一个合理的起点。一旦您有更多使用大整数的经验,您就可以进入更高级的方法。 -
整数除法绝对不是 NP-anything。它可以在大致
O(N*log(N))中被证明是正确的。它涉及使用 FFT 和牛顿法。为了以可证明正确的方式正确截断答案,还需要乘回 + 校正步骤。但这只会增加大 O 因素,并不会增加复杂性。 -
如果您正在尝试长手方法:在开始之前将两个操作数左对齐,因此每个操作数的 ms 位都是
1。 -
Mysticial 提到的技术是高级方法。人们不能期望 Wikipedia 文章成为此类方法的最终参考。一般来说,除法可以映射回乘法(这也意味着从 big-O 的角度来看,除法并不比乘法复杂),并且非常长整数的快速乘法方法可能涉及 FFT。
标签: c algorithm math biginteger division