2012-05-10 102 views
7

在過去的幾個小時裏,我一直在用Python做實驗。我寫了一個遞歸函數,返回遞歸(x)爲x!在Python和Java中,比較兩者。這兩段代碼是相同的,但由於某種原因,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通過NUM-1,直到它達到0,並輸出該結果乘以本身。在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代碼返回2076180480,這是不是正確的答案,我不知道爲什麼。

兩個代碼去相同的過程:

  • 檢查num是零
  • 如果num不爲零
    • NUM = NUM​​乘以NUM的遞歸 - 1
  • 如果num爲零
    • 返回1,結束那個遞歸調用堆棧,c ausing每返回NUM開始乘以
  • 返回NUM

在Python中沒有括號;我以爲改變了一些東西,所以我從Java代碼中刪除了括號,但它沒有改變。將布爾(num!= 0)更改爲(num> 0)也不會改變任何內容。向else添加if語句提供了更多的上下文,但值仍然相同。

打印在每一點上NUM的值給出的函數是如何出錯的想法:

的Python:

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返回負數,就好像函數返回負數,即使num不應低於零。

Python和Java代碼都採用相同的過程,但它們返回的參數卻不盡相同。這是爲什麼發生?

+6

Integer溢出... – Mysticial

+3

Python從int自動提升爲long,而java自動提升。 – jamylak

+0

這是一個很好的問題,因爲這裏的所有問題回答者都能立即理解問題,但除非您已經知道問題所在,否則這是您無法真正搜索的問題。 –

回答

11

兩個詞 - 整數溢出

雖然不是在蟒蛇的專家,我認爲它可以根據自己的需要擴展整數類型的大小。

但是,在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 

而且你可以看到第二個輸出是至少4個字節的4個輸出

+1

有趣。你能提供上下文嗎? – Zolani13

+0

說真的,OP的狀態是他/她是一個初學者 - 在這裏提供一些細節。 – kaveman

+1

@ Zolani13 - 請參閱編輯。 – MByD

2

與Java的內置支持,Python已經爲long integers無限精度。在Java中,整數限制爲32位,並將爲overflow

1

正如其他已寫,你會溢出;這些數字根本不適合java的數據類型表示。對於java沒有的地方,Python具有內置的bignum功能。

嘗試一些較小的值,你會看到你的Java代碼工作正常。

1

Java的int範圍

INT 4個字節,符號(2的補數)。 -2,147,483,648至2,147,483,647。像所有的數字類型一樣,int可以被轉換成其他數字類型(byte,short,long,float,double)。當有損轉換完成時(例如int轉換爲字節),轉換將以較小類型的長度爲模來完成。

這裏的int範圍是有限的

0

的問題是Java很簡單..
堂妹整數的最大限制是2147483647ü可以通過System.out.println(Integer.MAX_VALUE); 打印和最小是System.out.println(Integer.MIN_VALUE);

0

因爲在java版本中,你存儲的編號爲int,我相信它是32位的。考慮你可以用二位二進制來存儲的最大(無符號)數字:11這是十進制數字3。可以存儲四位二進制數的最大數是1111,這是十進制數15。 32位(帶符號)號碼不能存儲大於2,147,483,647的任何數字。當你試圖存儲一個比這更大的數字時,它會突然迴繞並開始從負數開始計數。這被稱爲溢出。

如果你想嘗試存儲更大的數字,請嘗試長時間。

相關問題