Python v 3.5.2和v 2.7.12中的结果不同,但v 2.7.12是否正确?

时间:2020-11-30 16:47:44

Let me preface my question by saying I know that around Python 3, the "limitless long" was integrated into the int so effectively ints in Python can be as large as your RAM.

让我先说一下我的问题,我知道围绕Python 3,“无限长”被集成到int中,所以Python中的有效内容可以和你的RAM一样大。

I'm comparing Java and Python. The following are a Python and Java program. They do the same thing.

我正在比较Java和Python。以下是Python和Java程序。他们做同样的事情。

Python:

def answer(n):
    count = 0
    t = int(n)
    while (t!=1):
        t = t+1 if (t%2==1) else t/2
        count += 1
    return count

Java:

static int answer(String n){
    int count = 0;
    BigInteger t = new BigInteger(n)

    while(!t.equals(BigInteger.ONE)){
        t = ((t.remainder(new BigInteger("2"))).equals(BigInteger.ONE))
            ?t.add(new BigInteger("1"))
            :t.divide(new BigInteger("2"));
        count++;
    }
    return count;
}

Then I wrote a simple bash script to run the java and python (as version 2.7.12, and 3.5.2) and compares their output.

然后我编写了一个简单的bash脚本来运行java和python(如2.7.12版和3.5.2版)并比较它们的输出。

#!/bin/bash
    i=$1
    a=`java    Solution    $i`
    b=`python  Solution.py $i`
    c=`python3 Solution.py $1`

    echo "INPUT: $1"
    echo ""
    echo "LANGUAGE: VERSION:  RESULT:"
    echo "--------  --------- ------"
    echo "Java      1.8.0_151   $a"
    echo "Python    2.7.12      $b"
    echo "Python3   3.5.2       $c"

Here are a few sample runs. The RESULT column is what's important.

以下是一些示例运行。 RESULT列是重要的。

INPUT: 123

LANGUAGE: VERSION:  RESULT:
--------  --------- ------
Java      1.8.0_151   9
Python    2.7.12      9
Python3   3.5.2       9


INPUT: 123456789

LANGUAGE: VERSION:  RESULT:
--------  --------- ------
Java      1.8.0_151   39
Python    2.7.12      39
Python3   3.5.2       39


INPUT: 12345678998765

LANGUAGE: VERSION:  RESULT:
--------  --------- ------
Java      1.8.0_151   61
Python    2.7.12      61
Python3   3.5.2       61


INPUT: 123456789987654321

LANGUAGE: VERSION:  RESULT:
--------  --------- ------
Java      1.8.0_151   84
Python    2.7.12      84
Python3   3.5.2       82

So they all pretty much yield the same results until the input gets sufficiently large and then you can see for the last one, that the results are different. Pretty much every number larger than this yields differing results.

所以他们几乎产生相同的结果,直到输入足够大,然后你可以看到最后一个,结果是不同的。几乎每个大于此的数字都会产生不同的结果。

Shouldn't Python3's int and Java's BigInteger get the same result?

Python3的int和Java的BigInteger不应该得到相同的结果吗?

Shouldn't Python v.2 be the one getting different results?

Python v.2不应该得到不同的结果吗?

Which one is actually wrong and why? Java and Python3 or just Python v.2.7.12?

哪一个实际上是错的,为什么? Java和Python3还是只是Python v.2.7.12?

How can I correct whichever is wrong to have the correct output?

如何才能纠正输出正确的错误?

1 个解决方案

#1


3  

The problem actually isn't related to the limit on integer literals in Python 2. That's just a red-herring. Your real problem is that the division operator / behaves different in Python 2 than in Python 3.

这个问题实际上与Python 2中的整数文字限制无关。这只是一个红鲱鱼。你真正的问题是,除了Python 3之外,Python 2中的除法运算符/行为也不同。

PEP 238 documents this change:

PEP 238记录了这一变化:

The current division (/) operator has an ambiguous meaning for numerical arguments: it returns the floor of the mathematical result of division if the arguments are ints or longs, but it returns a reasonable approximation of the division result if the arguments are floats or complex. This makes expressions expecting float or complex results error-prone when integers are not expected but possible as inputs.

当前的除法运算符(/)对数值参数有一个模糊的含义:如果参数是整数或长整数,它返回除数的数学结果的底限,但如果参数是浮点数或复数,则它返回除法结果的合理近似值。这使得表达式期望浮点或复杂结果在不期望整数但可能作为输入时容易出错。

We propose to fix this by introducing different operators for different operations: x/y to return a reasonable approximation of the mathematical result of the division ("true division"), x//y to return the floor ("floor division"). We call the current, mixed meaning of x/y "classic division".

我们建议由不同的操作引入不同的运营商来解决这个问题:X / Y返回除法的数学计算结果的合理近似(“真师”)中,x // y以返回地面(“楼师”)。我们称之为x / y“经典分裂”的当前混合含义。

Because of severe backwards compatibility issues, not to mention a major flamewar on c.l.py, we propose the following transitional measures (starting with Python 2.2):

由于严重的向后兼容性问题,更不用说c.l.py上的主要火焰战争,我们提出以下过渡措施(从Python 2.2开始):

  • Classic division will remain the default in the Python 2.x series; true division will be standard in Python 3.0.

    Classic Division仍然是Python 2.x系列中的默认值;真正的除法将成为Python 3.0的标准。

  • The // operator will be available to request floor division
    unambiguously.

    //运营商可以明确地请求楼层划分。

  • The future division statement, spelled from __future__ import
    division
    , will change the / operator to mean true division throughout the module.

    未来的部门声明,从__future__导入部门拼写,将改变/运算符,表示整个模块中的真正划分。

  • A command line option will enable run-time warnings for classic
    division applied to int or long arguments; another command line
    option will make true division the default.

    命令行选项将启用应用于int或long参数的经典除法的运行时警告;另一个命令行选项将使true除以默认值。

  • The standard library will use the future division statement and the
    // operator when appropriate, so as to completely avoid classic
    division.

    标准库将在适当时使用future division语句和//运算符,以完全避免经典除法。

Thus, if you want your Python code to behave correctly when the input is 123456789987654321, you need to use the floor division operator //:

因此,如果您希望Python代码在输入为123456789987654321时正常运行,则需要使用楼层除法运算符//:

def answer(n):
    count = 0
    t = int(n)
    while t != 1:
        t = t + 1 if (t % 2==1) else t // 2
        count += 1
    return count

#1


3  

The problem actually isn't related to the limit on integer literals in Python 2. That's just a red-herring. Your real problem is that the division operator / behaves different in Python 2 than in Python 3.

这个问题实际上与Python 2中的整数文字限制无关。这只是一个红鲱鱼。你真正的问题是,除了Python 3之外,Python 2中的除法运算符/行为也不同。

PEP 238 documents this change:

PEP 238记录了这一变化:

The current division (/) operator has an ambiguous meaning for numerical arguments: it returns the floor of the mathematical result of division if the arguments are ints or longs, but it returns a reasonable approximation of the division result if the arguments are floats or complex. This makes expressions expecting float or complex results error-prone when integers are not expected but possible as inputs.

当前的除法运算符(/)对数值参数有一个模糊的含义:如果参数是整数或长整数,它返回除数的数学结果的底限,但如果参数是浮点数或复数,则它返回除法结果的合理近似值。这使得表达式期望浮点或复杂结果在不期望整数但可能作为输入时容易出错。

We propose to fix this by introducing different operators for different operations: x/y to return a reasonable approximation of the mathematical result of the division ("true division"), x//y to return the floor ("floor division"). We call the current, mixed meaning of x/y "classic division".

我们建议由不同的操作引入不同的运营商来解决这个问题:X / Y返回除法的数学计算结果的合理近似(“真师”)中,x // y以返回地面(“楼师”)。我们称之为x / y“经典分裂”的当前混合含义。

Because of severe backwards compatibility issues, not to mention a major flamewar on c.l.py, we propose the following transitional measures (starting with Python 2.2):

由于严重的向后兼容性问题,更不用说c.l.py上的主要火焰战争,我们提出以下过渡措施(从Python 2.2开始):

  • Classic division will remain the default in the Python 2.x series; true division will be standard in Python 3.0.

    Classic Division仍然是Python 2.x系列中的默认值;真正的除法将成为Python 3.0的标准。

  • The // operator will be available to request floor division
    unambiguously.

    //运营商可以明确地请求楼层划分。

  • The future division statement, spelled from __future__ import
    division
    , will change the / operator to mean true division throughout the module.

    未来的部门声明,从__future__导入部门拼写,将改变/运算符,表示整个模块中的真正划分。

  • A command line option will enable run-time warnings for classic
    division applied to int or long arguments; another command line
    option will make true division the default.

    命令行选项将启用应用于int或long参数的经典除法的运行时警告;另一个命令行选项将使true除以默认值。

  • The standard library will use the future division statement and the
    // operator when appropriate, so as to completely avoid classic
    division.

    标准库将在适当时使用future division语句和//运算符,以完全避免经典除法。

Thus, if you want your Python code to behave correctly when the input is 123456789987654321, you need to use the floor division operator //:

因此,如果您希望Python代码在输入为123456789987654321时正常运行,则需要使用楼层除法运算符//:

def answer(n):
    count = 0
    t = int(n)
    while t != 1:
        t = t + 1 if (t % 2==1) else t // 2
        count += 1
    return count