1

階乗を解決するアプリケーションを作成しましたが、変数に 20 桁を超える数値を入力するとlong、負の数値が返されます。longC# の変数が制限を超えたときに負の値を返す理由を知りたいですか? こんなはずじゃないの?

4

8 に答える 8

11

これは、オーバーフローと呼ばれる非常に正常な動作です。

最初のステップとして、それをエラーに変えます

checked
{
    // your calculations
}

そして、この本には、すべてのビットとバイトを含む完全な説明があります.


これは、それを理解するのに役立つかもしれません:

static void Main2(string[] args)
{
    short s = 0;
    Console.WriteLine("Dec: {0,6} Hex {0:X4}", s);
    s -= 1;
    Console.WriteLine("Dec: {0,6} Hex {0:X4}", s);

    s = short.MaxValue;
    Console.WriteLine("Dec: {0,6} Hex {0:X4}", s);
    s += 1;
    Console.WriteLine("Dec: {0,6} Hex {0:X4}", s);
    Console.WriteLine(s == short.MinValue);    // is MaxValue+1 == MinValue ?
}

印刷します

Dec:      0 Hex 0000
Dec:     -1 Hex FFFF
Dec:  32767 Hex 7FFF
Dec: -32768 Hex 8000
True

16 進文字をビットとして読み取る:

0 = 0000
1 = 0001
7 = 0111
8 = 1000
F = 1111

最上位 (左端) ビットが+/-符号として使用されていることがわかります。

于 2012-10-02T18:52:59.647 に答える
4

なぜ負になるのかは誰もがすでに述べているので、階乗関数を変更する方法を説明します。BigIntegerを使用します (.NET 4.0 を使用していると仮定します)。

static BigInteger Factorial(BigInteger bigInt) {
    if (bigInt == 0) {
        return 0;
    }
    else if (bigInt == 1) {
        return 1;
    }
    else {
        return bigInt * Factorial(bigInt - 1);
    }
}
于 2012-10-02T18:59:37.427 に答える
3

ドキュメントごと:

-9,223,372,036,854,775,808 から 9,223,372,036,854,775,807 (9.2...E+18) までの範囲の符号付き 64 ビット (8 バイト) 整数を保持します。

20! = 2.432902e+18
21! = 5.1090942e+19

ご覧の通り21!の上限をはるかに超えていlongます。

C# データ型のより良いリンク:

整数型 浮動小数点型

20 を超える階乗を計算することを計画している場合は、浮動小数点型にステップアップする必要があります。

于 2012-10-02T18:54:42.390 に答える
1

これは算術オーバーフローと呼ばれます。

4 ビットの例:

 1101
+0101
-----
10010

ご覧のとおり、正解には 5 ビットが必要ですが、これを 4 ビットに格納するにはどうすればよいでしょうか?! オーバーフローが発生する必要があります。

直接の質問に答えるために、値は署名されているため負になり、オーバーフローすると下限にラップアラウンドします。

于 2012-10-02T18:57:01.903 に答える
1

c# のすべての数値型は max 関数をサポートしているため、Long.MaxValueで制限がわかります。2 の補数でエンコードされた数値の上位ビットの設定に関係する負の値になる理由については、

于 2012-10-02T18:53:37.717 に答える
1

longデータ型にはMSDNリファレンスがあります。基本的に、あなたが私たちに伝えていることは、すべての話ではありません。この長い上限は9.223372037x10^18であり、階乗の 20 は2.432902008x10^18の上限よりも小さいですlong

実際に何が起こっているかを確認できるように、いくつかのコードを投稿します。

于 2012-10-02T18:57:41.040 に答える
1

この種のオーバーフローが望ましくない場合は、 の使用を検討してBigIntegerください。これを使用するには、C# プロジェクトに .NET アセンブリへの参照を含める必要がありますSystem.Numerics.dll。そして、コードファイルに含める必要があります

using System.Numerics;

上に。

于 2012-10-02T18:59:43.723 に答える
1

はい、21です!長い制限よりも素晴らしいですが、20! ではありません。このように溢れています。

于 2012-10-02T18:52:46.057 に答える