【问题标题】:How can I perform division in a program, digit by digit?如何在程序中逐位执行除法?
【发布时间】:2010-02-25 23:30:18
【问题描述】:

我正在写一个类似于 mpz (C) 或 BigInteger (Java) 的类。这只是为了好玩,所以请不要继续说我不应该自己写。

我有一个类似于:

public class HugeInt
{
    public List<Integer> digits;

    public HugeInt(String value)
    {
        // convert string value into its seperate digits. 
        // store them in instance variable above
    }
}

现在,执行这个类的 add() 和 subtract() 方法非常简单。这是一个例子:

private List<Integer> add(List<Integer> a, List<Integer> b)
    {
        List<Integer> smallerDigits = (compareDigits(a,b) < 0) ? a : b;
        List<Integer> largerDigits = (compareDigits(a,b) >= 0) ? a : b;
        List<Integer> result = new ArrayList<Integer>();

        int carry = 0;

        for(int i = 0; i < largerDigits.size(); i++)
        {
            int num1 = largerDigits.get(i);
            int num2 = (i < smallerDigits.size()) ? smallerDigits.get(i) : 0;

            result.add((num1 + num2 + carry) % 10);
            carry = ((num1 + num2 + carry) / 10);
        }

        if (carry != 0) result.add(carry);

        return result;
    }

同样,做乘法也没有那么难。

我在维基百科上看到Division Algorithms 上有一个页面,但我不确定哪个适合我正在尝试做的事情。

因为这些正整数(表示为数字)可以任意长,所以我想确保我不会尝试在逐个数字的基础上进行任何操作。

但是,谁能指出我正确的方向来除以表示为List&lt;Integer> 的两个数字?另外,我可以忽略余数,因为这是整数除法。

【问题讨论】:

  • +1:我非常喜欢这个问题。我会整理一个算法,只是为了好玩。
  • Knuth 的“半数值算法”非常详细地探讨了这个主题。

标签: c# java math division integer-division


【解决方案1】:

你可以只做long division,但这肯定不是最好的方法(edit:虽然看起来像这样的方法是一个很好的方法)。你可以看看other implementations 的大整数库,一点点Googling 会发现很多有用的信息。

【讨论】:

  • 实际上,纸笔长除法方法与许多大整数除法算法对常见尺寸的工作方式非常接近。为了过于简单化,您使用少量前导数字来估计商数,然后计算部分余数并重复。您需要检测您的估计何时错误并从中恢复。
【解决方案2】:

这可能有点矫枉过正,但如果这是您为了好玩而做的事情,您会喜欢阅读以下内容: http://www.fizyka.umk.pl/nrbook/c20-6.pdf (那是“C中的数值食谱”中的“任意精度的算术”)。 非常引人入胜,就像本书的大部分内容一样,有很好的解释和大量的代码。

【讨论】:

    【解决方案3】:

    因为我假设您只是在处理整数除法,所以这并不难。乘法是重复加法,除法是相反的——重复减法。所以你要做的是检查你可以从股息中减去多少次除数。比如10减去3就可以不

    【讨论】:

    • 不过,这不是一个个数字。我认为他想效仿长除法。
    • 我曾考虑过这一点,但认为它会非常低效。现在我想知道这是否足够,或者像比尔 K 所说的那样,最好模拟长除法。
    • @Mithrax,是的,当除以 1 之类的小数时,这将非常低效。您将迭代 N 次,其中 N 是您的大整数。 (如果你不把你的计数保留在另一个大整数中,你就有溢出原始整数类型的风险。)
    • @Mike:我还没有详细考虑过,但最初我认为您不需要单独遍历每个整数;根据位数的差异,您可以获得相当高的结果下限。如果该差异为零,那么您只需要从 1 循环到 9。
    • 嗯...重新考虑,不确定“相当高”会有多高,在某些情况下似乎不太高。
    【解决方案4】:

    这篇文章A Larger Integer 没有展示如何为“更大的整数”实现逐位运算,但它确实展示了如何根据两种 Int64 类型实现一个(显然功能齐全的)128 位整数。我想扩展使用 Int64 类型数组来产生任意长度整数的方法不会太难。我只是花了几分钟回顾这篇文章,乘法的实现看起来可以涉及任意长度。

    文章展示了如何使用binary division实现除法(商和余数)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-14
      • 1970-01-01
      • 2017-04-25
      • 2023-02-11
      • 2011-04-04
      • 2015-10-16
      • 1970-01-01
      相关资源
      最近更新 更多