7

ここ数時間、初心者として Python を試してきました。recurse(x) を x として返す再帰関数を書きました。Python と Java で、2 つを比較します。2 つのコードは同じですが、何らかの理由で Python は機能しますが、Java は機能しません。Python では、次のように書きました。

x = int(raw_input("Enter: "))

def recurse(num):
    if num != 0:
        num = num * recurse(num-1)
    else:
        return 1

    return num 

print recurse(x)

変数numは、0 になるまで num-1 を乗算し、その結果を出力します。Java では、コードは非常に似ていますが、より長くなります。

public class Default {
    static Scanner input = new Scanner(System.in);
    public static void main(String[] args){

            System.out.print("Enter: ");
            int x = input.nextInt();
            System.out.print(recurse(x));


}

    public static int recurse(int num){

    if(num != 0){
    num = num * recurse(num - 1);
    } else {
        return 1;
    }

    return num;

}

}

25 を入力すると、Python コードは 1.5511x10E25 を返します。これは正解ですが、Java コードは 2,076,180,480 を返します。これは正解ではありません。理由はわかりません。

どちらのコードも同じプロセスをたどります。

  • num がゼロかどうかを確認する
  • num がゼロでない場合
    • num = num に num - 1 の再帰を掛けた値
  • 数値がゼロの場合
    • 1 を返し、再帰呼び出しのスタックを終了し、返されたすべての num の乗算を開始します。
  • 戻り値

Python には括弧がありません。なんか変わったなと思ってJavaコードから括弧を外したのですが、変わりませんでした。ブール値 (num != 0) を (num > 0 ) に変更しても、何も変わりませんでした。if ステートメントを else に追加すると、より多くのコンテキストが提供されましたが、値は同じままでした。

すべてのポイントでnumの値を出力すると、関数がどのようにうまくいかないかがわかります。

パイソン:

1
2
6
24
120
720
5040
40320
362880
3628800
39916800
479001600
6227020800
87178291200
1307674368000
20922789888000
355687428096000
6402373705728000
121645100408832000
2432902008176640000
51090942171709440000
1124000727777607680000
25852016738884976640000
620448401733239439360000
15511210043330985984000000
15511210043330985984000000

着実な増加。Java では:

 1
 2 
 6  
 24
 120 
 720
 5040
 40320
 362880
 3628800
 39916800
 479001600
 1932053504
 1278945280
 2004310016
 2004189184
-288522240
-898433024
 109641728
-2102132736 
-1195114496
-522715136
 862453760
-775946240
 2076180480
 2076180480

着実な増加ではありません。実際には、関数が負の数を返しているかのように、num は負の数を返しています。

Python と Java のコードはどちらも同じ手順を踏んでいますが、大幅に異なる値を返しています。なぜこうなった?

4

6 に答える 6

11

2 ワード -整数オーバーフロー

Python の専門家ではありませんが、必要に応じて整数型のサイズを拡張できると思います。

ただし、Java では、int型のサイズは 32 ビットに固定されており、int符号付きであるため、実際には正の数を表すのに 31 ビットしかありません。割り当てた数値が最大値を超えると、int がオーバーフローします (つまり、整数を表す場所がありません)。

C 言語ではこのような場合の動作は定義されていませんが、Java では明確に定義されており、結果の最小 4 バイトのみが使用されます。

例えば:

System.out.println(Integer.MAX_VALUE + 1);
// Integer.MAX_VALUE = 0x7fffffff

結果:

-2147483648
// 0x7fffffff + 1 = 0x800000000

編集

わかりやすくするために、別の例を示します。次のコード:

int a = 0x12345678;
int b = 0x12345678;
System.out.println("a*b as int multiplication (overflown) [DECIMAL]: " + (a*b));
System.out.println("a*b as int multiplication (overflown) [HEX]: 0x" + Integer.toHexString(a*b));
System.out.println("a*b as long multiplication (overflown) [DECIMAL]: " + ((long)a*b));
System.out.println("a*b as long multiplication (overflown) [HEX]: 0x" + Long.toHexString((long)a*b));

出力:

a*b as int multiplication (overflown) [DECIMAL]: 502585408
a*b as int multiplication (overflown) [HEX]: 0x1df4d840
a*b as long multiplication (overflown) [DECIMAL]: 93281312872650816
a*b as long multiplication (overflown) [HEX]: 0x14b66dc1df4d840

そして、2 番目の出力が 4 つの出力のうちの最小の 4 バイトであることがわかります。

于 2012-05-10T04:41:15.140 に答える
2

Java とは異なり、Python には無制限の精度の長整数のサポートが組み込まれています。Java では、整数は 32 ビットに制限されており、オーバーフローします。

于 2012-05-10T04:45:52.797 に答える
1

他の人がすでに書いたように、オーバーフローします。数字は単に Java のデータ型表現に収まりません。Python には、java にはない組み込みの bignum 機能があります。

小さい値をいくつか試してみると、Java コードが正常に動作することがわかります。

于 2012-05-10T04:45:54.997 に答える
1

Javaのint範囲

int 4 バイト、符号付き (2 の補数)。-2,147,483,648 ~ 2,147,483,647。すべての数値型と同様に、int は他の数値型 (byte、short、long、float、double) にキャストできます。非可逆キャスト (int から byte など) が行われる場合、変換は小さい方の型の長さを法として行われます。

ここでの範囲intは限られています

于 2012-05-10T04:46:08.197 に答える
0

問題は非常に単純です
..Javaでは、整数の最大制限は2147483647印刷できSystem.out.println(Integer.MAX_VALUE); 、最小値はSystem.out.println(Integer.MIN_VALUE);

于 2012-05-10T04:48:17.807 に答える
0

Javaバージョンでは、番号をint32ビットと思われるものとして保存するためです。バイナリの 2 ビットで格納できる最大の (符号なし) 数値を考えてみましょう: 11 は 10 進数の数値 3 です。2 進数で 4 ビットを格納できる最大の数は 1111 で、10 進数では 15 です。32 ビット (符号付き) の数値は、2,147,483,647 より大きい値を格納できません。これより大きい数値を保存しようとすると、突然ラップアラウンドし、負の数値からカウントアップを開始します。これをオーバーフローと呼びます。

より大きな数を格納したい場合は、長く試してください。

于 2012-05-10T04:50:55.683 に答える