2012-05-10 104 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的任何数字。当你试图存储一个比这更大的数字时,它会突然回绕并开始从负数开始计数。这被称为溢出。

如果你想尝试存储更大的数字,请尝试长时间。

相关问题