【问题标题】:Why do these two similar pieces of code produce different results?为什么这两段相似的代码会产生不同的结果?
【发布时间】:2012-05-10 13:04:16
【问题描述】:

在过去的几个小时里,我一直在尝试使用 Python 作为初学者。我写了一个递归函数,它返回 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 的值可以了解函数是如何出错的:

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 代码都在执行相同的过程,但它们返回的值却大相径庭。为什么会这样?

【问题讨论】:

  • 整数溢出...
  • Python 会自动从 int 提升为 long,而 java 不会。
  • 这是一个很好的问题,因为这里所有的问答者都能立即理解这个问题,但除非你已经知道问题的名称,否则你无法真正搜索它。

标签: java python


【解决方案1】:

两个字 - 整数溢出

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

【讨论】:

  • 有趣。你能提供上下文吗?
  • 说真的,OP 说她/他是初学者 - 在这里提供更多细节。
  • Java 中的整数由固定数量的字节表示,当达到这些字节表示的最大十进制数时,它会环绕成负值(最终返回 0),另一方面是 python hand 会动态增加字节数
  • Java 中的整数只有 32 位。如果你使用多头,你可能会有更好的运气。它们用 64 位编码值。两者中最左边的位是符号位。
  • @Zolani13 它会以同样的方式工作......直到一个点(64 位,在 2^63 = 9,223,372,036,854,775,807 处溢出)
【解决方案2】:

与 Java 不同,Python 内置了对无限精度的 long integers 的支持。在 Java 中,整数被限制为 32 位,并且将 overflow

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

      Java 的 int 范围

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

      这里int的范围是有限的

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          【解决方案6】:

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

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-11-13
            • 1970-01-01
            • 2023-04-11
            • 1970-01-01
            • 2022-12-05
            相关资源
            最近更新 更多