【问题标题】:Algorithm for dividing very large numbers用于划分非常大的数字的算法
【发布时间】:2011-02-22 11:21:25
【问题描述】:

我需要编写一个算法(我不能使用任何 3rd 方库,因为这是一个分配)来划分(整数除法,浮动部分不重要)非常大的数字,例如 100 - 1000 位。我找到了http://en.wikipedia.org/wiki/Fourier_division 算法,但我不知道这是否是正确的方法。你有什么建议吗?

1) check divisior < dividend, otherwise it's zero (because it will be an int division)
2) start from the left
3) get equal portion of digits from the dividend
4) if it's divisor portion is still bigger, increment digits of dividend portion by 1
5) multiply divisor by 1-9 through the loop
6) when it exceeds the dividend portion, previous multiplier is the answer
7) repeat steps 3 to 5 until reaching to the end

【问题讨论】:

  • “因为这是作业”...添加作业标签?
  • 如果你能在纸上做长除法,你已经知道解决这个问题的好算法了。
  • @Neil:嗯,我不希望收到代码示例。我只是希望学习一些数学技巧来超越这些语言限制。
  • @pocoa:那么你应该添加 homework 标签。标签表示您需要帮助/想法/建议,但您不希望为您完成工作。
  • @Carl:我认为当您需要将 120 位数字除以 75 时,这并不容易 :) 这就是我问的原因。

标签: c++ algorithm math largenumber


【解决方案1】:

我想像在小学那样划分“长”路将是一条潜在的路线。我假设您将原始数字作为字符串接收,所以您要做的是解析每个数字。示例:

第 0 步:

   /-----------------
13 | 453453453435....

第 1 步:“13 变成 4 多少次?0

     0
   /-----------------
13 | 453453453435....

第 2 步:“13 变成 45 多少次?3

     03
   /-----------------
13 | 453453453435....
   - 39
     --
      6

第 3 步:“13 变成 63 多少次?4

等等等等。使用这种策略,你可以有任何数字长度,并且只需要在内存中为 int(除数)和 double(除数)保存足够的数字。 (假设我的这些条款是正确的)。您将结果存储为结果字符串中的最后一位。

当您达到没有数字剩余且计算不会进行 1 次或更多次的点时,您会返回已格式化为字符串的结果(因为它可能比 int 大)。

【讨论】:

  • 很久以前,我正在阅读 MP 库的源代码(我认为是gmplib.org)。它将这种方法用于“中等大小”的数字(大于 long,小于大约 30 个字节),然后切换到傅立叶除法来处理非常大的数字。我很想看看这是否仍然是使用的方法。
  • @rschuler:所以傅里叶分割算法可以解决这个问题,对吧?
  • 您的解决方案仅对小除数有用。当除数也是一个大数时,情况要复杂得多。
【解决方案2】:

对大数实现的最简单的除法算法是移位和减法。

if numerator is less than denominator then finish
shift denominator as far left as possible while it is still smaller than numerator
set bit in quotient for amount shifted
subtract shifted denominator from numerator
repeat
the numerator is now the remainder

转移不必是字面的。例如,您可以编写一个算法来从另一个值中减去一个左移值,而不是在减去之前实际将整个值左移。比较也一样。

长除法很难实现,因为长除法的步骤之一是长除法。如果除数是一个整数,那么你可以很容易地进行长除法。

【讨论】:

    【解决方案3】:

    Knuth, Donald,计算机编程艺术,ISBN 0-201-89684-2,第 2 卷:半数值算法,第 4.3.1 节:经典算法

    【讨论】:

    • 谷歌搜索;你会发现很多关于“改进”算法的论文,Knuth 如此尊敬地记录了这一点。
    • @pocoa,你真的应该从你学校的图书馆里得到它,这是一本很棒的书。
    • 有没有人碰巧在 Knuth 算法 D 的类似 C 语言中实现了一对一的幼稚但有效的实现?我对多个步骤感到困惑,例如 D1 引入新数字 u_(m+n) 如果 d = 1 则应设置为 0,但除此之外呢?在步骤 D4 中,如果任何数字 skanthak.homepage.t-online.de/division.html,但是有很多优化等等。
    【解决方案4】:

    您可能应该尝试使用长除法之类的方法,但使用计算机单词而不是数字。

    在高级语言中,将“数字”视为最大固定精度整数的一半是最方便的。对于长除法,您将需要处理部分中间结果可能相差 1 的情况,因为您的固定精度除法只能处理任意精度除数的最重要部分。

    有更快、更复杂的任意精度算术方法。查看相应的wikipedia page。特别是,如果仔细实施 Newton-Raphson 方法,可以确保除法的时间性能在任意精度乘法的常数因子内。

    【讨论】:

      【解决方案5】:

      除非你的部分作业是完全原创的,否则我会使用我(我假设你)在小学教过的用于手工进行大除法的算法。

      【讨论】:

      • 是的,如果我找不到更好的算法,我会实现自己的:)
      • 限制搜索“更好”算法的时间。在等待答案时实施小学算法。 :-)
      • @Thomas:啊哈哈哈..也许这应该是答案! :)) 谢谢提醒!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多