繁体   English   中英

为什么这两个相似的代码片会产生不同的结果?

[英]Why do these two similar pieces of code produce different results?

在过去的几个小时里,我一直在尝试使用Python作为begninner。 我写了一个递归函数,它将recurse(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代码返回2,076,180,480,这不是正确的答案,我不知道为什么。

两个代码都遵循相同的过程:

  • 检查num是否为零
  • 如果num不为零
    • num = num乘以num - 1的递归
  • 如果num为零
    • 返回1,结束那一堆递归调用,并使每个返回的num开始相乘
  • 返回号码

python中没有括号; 我认为以某种方式改变了一些东西,所以我从Java代码中删除了括号,但它没有改变。 将布尔值(num!= 0)更改为(num> 0)也没有改变任何内容。 向else添加if语句提供了更多上下文,但值仍然相同。

在每个点打印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返回负数 ,就好像函数返回负数一样,即使num不应该低于零。

Python和Java代码都采用相同的过程,但它们返回的是不同的值。 为什么会这样?

两个字 - 整数溢出

虽然不是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

你可以看到第二个输出是4输出中至少4个字节

与Java不同,Python内置支持无限精度的长整数 在Java中,整数限制为32位并且将溢出

正如其他人已经写过的那样,你会溢出; 这些数字根本不适合java的数据类型表示。 Python有一个内置的bignum功能,而java则没有。

尝试一些较小的值,你会发现你的java代码工作正常。

Java的int范围

int 4个字节,有符号(二进制补码)。 -2,147,483,648至2,147,483,647。 像所有数字类型一样,int可以转换为其他数字类型(byte,short,long,float,double)。 当完成有损转换(例如,int到byte)时,转换以较小类型的长度为模。

这里int的范围是有限的

问题很简单..
在java中coz整数的最大限制是2147483647你可以通过System.out.println(Integer.MAX_VALUE);打印它System.out.println(Integer.MAX_VALUE); 最小的是System.out.println(Integer.MIN_VALUE);

因为在java版本中,您将数字存储为int ,我相信它是32位。 考虑一下你可以用二进制中的两位存储的最大(无符号)数字:11是十进制数字3。 可以以二进制形式存储四位的最大数字是1111,即十进制数15。 32位(带签名)号码不能存储大于2,147,483,647的任何内容。 当你试图存储一个比这更大的数字时,它会突然回绕并从负数开始计数。 这称为溢出。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM