大数计算出错:为什么会这样?

时间:2019-05-09 13:02:02

标签: python

我在repl.it中创建了一个小Python程序来说明Collat​​z猜想,它说如果以任何正整数n开头,然后递归应用以下操作:n / 2(如果n为偶数),则3n +如果n为奇数,则为1,则您将始终达到1。

这是代码:

invalid_input = 0

while(invalid_input == 0):
  n = input("Give me a positive integer: ")

  try: #check for positive integer. If it cannot do int(n) it means a string was entered, and it goes to except.
    if(int(n)>0):
      invalid_input = 1 #this is to tell the while loop above that the right input was entered
      print("Thank you.")
      print("Now loading:")

    else: #an integer was entered, but it was negative
      print("Please enter a positive integer")
  except: #a string was entered
    print("Please enter a positive integer")

n=int(n)
nentered = n #this will keep track of the initial n
npeak = n #this will keep track of the highest n reached
iteration = 1 #this will keep track of the number of iterations
iterationmax = 1 #this will keep tack of the iteration at which npeak was reached

while(n != 1):
  print("%5i:    %5i" % (iteration,n))
  if(n % 2 == 0): #divide by 2 if even
    n=n/2
  else: #if it is odd, multiply by 3 and add 1
    n=3*n+1
  iteration = iteration + 1
  if(n>npeak): #record the higher n and its iteration
    npeak = n
    iterationmax = iteration

有效。但是有一个问题:如果输入的数字足够大,例如6666666666666666666666666,那么它所做的事情确实很奇怪。这就是我得到的:

Give me a positive integer: 6666666666666666666666666
Thank you.
Now loading:
    1:    6666666666666666666666666
    2:    3333333333333333277409280
    3:    1666666666666666638704640
    4:    833333333333333319352320
    5:    416666666666666659676160
    6:    208333333333333329838080
    7:    104166666666666664919040
    8:    52083333333333332459520
    9:    26041666666666666229760
   10:    13020833333333333114880
etc

如您所见,我期望第二个数字恰好是3333333333333333333333333333,但是最后我得到的是不同的数字。 另一个示例,在第二次迭代中输入1000000000000000000000000会返回499999999999999991611392。

这可能是什么原因?

2 个答案:

答案 0 :(得分:1)

/的操作更改为//,以使它们不会导致(不准确的)浮点值。

所以这个:

if(n % 2 == 0): #divide by 2 if even
  n=n/2

应该是:

if(n % 2 == 0): #divide by 2 if even
  n=n//2

或按照Python约定正确设置的格式:

if n % 2 == 0:
    n //= 2

答案 1 :(得分:1)

@ruohola之所以说是正确的,是因为当您将浮点除法与单个/一起使用时,会发生一个浮点数被创建的情况。但是,由于数量太大,因此无法表示,因此将其舍入为最接近的最精确表示。因此,您将不得不使用//而不是/

但是,使用//是整数除法。这样就产生了一个比高浮点数更容易表示的整数。

here可以找到一个非常相似的问题,其中包含更多解释。