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

时间:2018-02-16 23:44:52

标签: java python long-integer biginteger

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

我正在比较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

爪哇:

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;
}

然后我编写了一个简单的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"

以下是一些示例运行。 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

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

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

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

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

如何更正输出正确的错误?

1 个答案:

答案 0 :(得分:3)

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

PEP 238 documents this change

  

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

     

我们建议通过为不同的操作引入不同的运算符来解决这个问题:x / y返回分区的数学结果的合理近似值(“真正的除法”),x // y返回底线(“楼层划分” “)。我们称之为x / y“经典分裂”的当前混合含义。

     

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

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

  •   
  • //运营商可以请求楼层分割   明确。

  •   
  • 未来的部门声明,拼写自__future__ import
    division
    ,将更改/运算符,表示真正的划分   模块。

  •   
  • 命令行选项将启用经典
    的运行时警告   除法适用于int或long参数;另一个命令行
      选项将使真正的除法成为默认值。

  •   
  • 标准库将使用未来的分部声明和
      //操作员在适当的时候,以完全避免经典
      分裂。

  •   

因此,如果您希望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