代码之家  ›  专栏  ›  技术社区  ›  Aaron

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

  •  3
  • Aaron  · 技术社区  · 6 年前

    在我的问题之前,我要说,我知道在Python 3周围,“无限长”被集成到int中,因此Python中的int可以有效地与RAM一样大。

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

    蟒蛇:

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

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

    下面是一些运行示例。结果列是最重要的。

    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 回复  |  直到 6 年前
        1
  •  3
  •   user2357112    6 年前

    这个问题实际上与Python 2中整数文本的限制无关。那只是转移视线。你的 真实的 问题是除法运算符 / Python 2中的行为与Python 3中的行为不同。

    PEP 238 documents this change :

    当前除法(/)运算符对于数值参数的含义不明确:如果参数为int或long,则返回除法数学结果的下限;如果参数为float或complex,则返回除法结果的合理近似值。这使得期望浮点或复杂结果的表达式在不期望整数但可能作为输入时容易出错。

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

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

    • 经典除法将保持Python 2中的默认值。x系列; 真正的除法在Python 3.0中是标准的。

    • 操作员可请求楼层划分
      毫不含糊地。

    • future division语句,拼写自 __future__ import
      division
      ,将更改 / 运算符表示整个真实除法 模块。

    • 命令行选项将为classic启用运行时警告
      除法应用于int或long参数;另一个命令行
      选项将使true division成为默认值。

    • 标准库将使用未来的division语句和
      // 操作员适当时,以完全避免经典
      分开

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