できない言語で非常に大きな数を処理することはできませんか?


15

言語構成体が特定の値より大きい数値を処理できない場合、非常に大きな数値(無限大-浮動小数点数まで)で計算を実行する方法について考えようとしています。

私はこの質問をするのは最初でも最後でもないと確信していますが、私が使用している検索用語はそれらの状況を処理するアルゴリズムを提供していません。むしろ、ほとんどの提案は言語の変更や変数の変更を提供したり、検索に無関係と思われることについて話したりします。だから私は少しの指導が必要です。

次のようなアルゴリズムをスケッチします。

  1. 言語の整数変数の最大長を決定します。

  2. 数値が変数の最大長の半分を超える場合、配列に分割します。(小さなプレイルームを与えます)

  3. 配列の順序[0] =右端の数字[n-max] =左端の数字

    例 番号:29392023配列[0]:23、配列[1]:20、配列[2]:39、配列[3]:29

変数の長さの半分をマークオフポイントとして設定したので、1、10、100などを計算できます。変数の最大長が0から9999999999までの10桁の場合、それを5桁に半分にすることで、遊び場ができます。

したがって、追加または乗算すると、array [0]の6番目の桁(右から)がarray [1]の最初の桁(右から)と同じ場所であることを確認する変数チェッカー関数を使用できます。

除算と減算には、私がまだ考えていない独自の問題があります。

プログラムがサポートできる数よりも多くの数をサポートする最良の実装について知りたい。


1
最初に思い浮かぶのは、JavaのBigIntegerです。docs.oracle.com
Ivan

これはここにいる人なら誰でも知っていて、特定の推奨事項を作成できる言語ですか、それともあいまいで独自の言語ですか?
FrustratedWithFormsDesigner

私はこれをどの言語にしたいのかまだわかりません。私はPHPを最もよく知っていますが、その言語でそれをしたくありません。Lispは魅力的です。私が読んだものから長さの制限がないからです。しかし、それがどのように機能するかを知りたいという私の個人的な欠陥は、私が島で立ち往生している場合、qbasicでそれを行う自由を持ちたいと思うようにします。(それも楽しみのためです、私は常に大きな数を計算することを考えており、いくつかのオンライン計算機はタスクには面倒です。)
マロー

回答:


25

使用している言語の任意の精度の算術(「多重精度」または「big num」とも呼ばれる)ライブラリを探しています。たとえば、Cを使用している場合は、GNU Bignum Library-> http://gmplib.org/を使用できます。

どのように機能するかを理解したい場合は、独自の大きなnumライブラリを作成して使用することもできます。これを処理する最も簡単な方法は、配列を使用することです。各要素は、使用している数字の数字です。その後、すべての関数を実装して、加算、減算、乗算、除算、べき乗などを行う必要があります。


5
当然の"桁"は相対的であり、多くのBIGNUMライブラリー(] [unsigned long型)2 ^ 64にベース256(符号なしバイト[])内の数字を使用する
ラチェットフリーク

1
私が理解したことを確認するだけで、「数字」はベースの256桁の配列になる可能性がありますか?私は間違っているかもしれないと思う、ベース256での計算はベース88よりも簡単ですが、それでもかなりの作業です...(少なくとも昨晩紙のハハでそれをやったとき)
マロー

1
「ベース256で数学を行うのはベース88より簡単です」。偽。それらも同様に簡単です。
S.Lott

2
S.Lott @:あなたが可能なビット演算を持っている場合ええと...、ベース256の上に数学をやってすることは間違いなく、ベース88よりも簡単です
ジェイソンS

1
独自の加算/減算/乗算を構築するのはかなり簡単です。ただし、バイナリで実装している場合を除き、除算は困難です。除算では、条件付き減算とビットシフトの演習になります。
ジェイソンS

13

それはよく知られている問題です:任意精度の算術

使用している言語でこの問題が解決しない場合は、最初に解決するサードパーティライブラリを探してみてください。見つからない場合や興味がある場合は、実装してみてください。ウィキペディアの記事には、古典的な実装への良い参照があります。


6

多数を処理する場合、おそらく最も基本的な設計決定の1つは、多数をどのように表現するかです。

文字列、配列、リスト、またはカスタム(自家製)ストレージクラスになります。

その決定が行われた後、実際の数学演算は小さな部分に分解され、intやintegerなどのネイティブ言語タイプで実行されます。

結果の大きな数値を文字列として格納する非常に初歩的な ADDITIONの例をC#.Netに含めました。着信「番号」も文字列であるため、非常に「大きい」番号で送信できるはずです。この例は、単純にするために整数のみを対象としていることに注意してください。

文字列を使用しても、次のように文字数または数字の「数字」に制限があります。

.NET文字列の最大長は?

しかし、.Netのint32またはint64ネイティブ型をはるかに超える、非常に大きな数を追加できます。

とにかく、ここに文字列ストレージの実装があります。

/// <summary>
/// Adds two "integers".  The integers can be of any size string.
/// </summary>
/// <param name="BigInt1">The first integer</param>
/// <param name="BigInt2">The second integer</param>
/// <returns>A string that is the addition of the two integers passed.</returns>
/// <exception cref="Exception">Can throw an exception when parsing the individual parts     of the number.  Callers should handle. </exception>
public string AddBigInts(string BigInt1, string BigInt2)
{
    string result = string.Empty;

    //Make the strings the same length, pre-pad the shorter one with zeros
    int length = (BigInt1.Length > BigInt2.Length ? BigInt1.Length : BigInt2.Length);
    BigInt1 = BigInt1.PadLeft(length, '0');
    BigInt2 = BigInt2.PadLeft(length, '0');

    int remainder = 0;

    //Now add them up going from right to left
    for (int i = (BigInt1.Length - 1); i >= 0; i--)
    {
        //If we don't encounter a number, this will throw an exception as indicated.
        int int1 = int.Parse(BigInt1[i].ToString());
        int int2 = int.Parse(BigInt2[i].ToString());

        //Add
        int add = int1 + int2 + remainder;

        //Check to see if we need a remainder;
        if (add >= 10)
        {
            remainder = 1;
            add = add % 10;
        }
        else
        {
            remainder = 0;
        }

        //Add this to our "number"
        result = add.ToString() + result;
    }

    //Handle when we have a remainder left over at the end
    if (remainder == 1)
    {
        result = remainder + result;
    }

    return result;
}

それがあなた自身の実装についてのアイデアを与えてくれることを願っています。サンプルコードはおそらく最適化されていないか、そのようなものではないことに注意してください。どうすればそれができるのか、いくつかのアイデアを提供することを意図しています。


涼しい!!ありがとう
マロー

-2

これは私のために速く動作します:

static string Add(string a, string b)
        {
            string c = null;

            if (Compare(a, b) < 0)
            {
                c = a;
                a = b;
                b = c;
            }

            StringBuilder sb = new StringBuilder();

            b = b.PadLeft(a.Length, '0');

            int r = 0;

            for (int i = a.Length - 1; i >= 0; i--)
            {
                int part = a[i] + b[i] + r - 96;

                if (part <= 9)
                {
                    sb.Insert(0, part);

                    r = 0;
                }
                else
                {
                    sb.Insert(0, part - 10);

                    r = 1;
                }
            }

            if (r == 1)
            {
                sb.Insert(0, "1");
            }

            return sb.ToString();
        }

2
このサイトは、概念的質問と回答は、物事を説明することが期待されています。説明の代わりにコードダンプをスローすることは、IDEからホワイトボードにコードをコピーするようなものです。見た目はよく、時には理解できるかもしれませんが、奇妙に感じます...ただ奇妙です。ホワイトボードにはコンパイラがありません
-gnat

このサイトはEXCHANGEなので、できる限りお互いに助け合うよう努めています。StackOverflowでそのようなコメントをする必要があるかもしれませんが、自分のアプローチを支援しようとしました。誰かがまだ説明が必要な場合、彼はそれを求めます。ここでは、最後から始めて、標準的な数学的加算を行います。
アンドラニックサルシアン

gnatに同意します。少なくとも、コードをダンプする前にアルゴリズムを説明してください。
フランクヒルマン

説明なしでコードをダンプすることは、コピーアンドゴーを奨励するようなものです。SoftwareEngineeringでどのように役立つかわかりません。StackOverflowにあるかもしれませんが、実際には両方のサイトにはまったく異なる目的があります。
ライヴ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.