首页 > 解决方案 > Python 没有正确划分大浮点数

问题描述

我正在编写一个程序来计算 100 的阶乘数字和。我们不允许使用循环结构或有程序状态;我们只应该使用递归。这意味着我将首先计算100!然后将答案中的每个数字加在一起。例如:10!= 3628800。3+6+2+8+8+0+0 = 27。

该程序使用 2 个递归循环设置。第一个循环是一个简单的递归结构,计算 n 的阶乘。使用 n = 100 可以正常运行。

接下来,为了使用递归添加数字,编写了一个由 3 个组件组成的函数。

  1. n % 10:这将隔离 n 的最后一位数字
  2. math.floor( n / 10 ) :一旦数字被隔离,我们需要将它从数字中删除。我们通过将 n 除以 10 并向下舍入到最接近的整数来做到这一点。
  3. return (n % 10) + Summation( math.floor( n / 10 )):这将在递归调用中添加每个孤立的数字

该程序在输入 22 时完美运行。但是,当尝试计算 23! 的数字总和时,math.floor(n % 10) 不能正确除法。

这是我使用 100 作为输入运行时的输出。第一行是计算出的阶乘,Mod 是最后一位,Divide 是阶乘除以 10(不四舍五入),New Num 是向下舍入的值。如您所见,New Num 没有准确划分

这里的大问题是,是什么让这个计算在如此高的值下不正确?这是否与 Python 的精度水平有关?谢谢!

代码:

'''
--------------------------------------------------------
Problem 20:
n! means n × (n − 1) × ... × 3 × 2 × 1

For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800,
and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.

Find the sum of the digits in the number 100!
----------------------------------------------------------
'''
import math


def Divide(n):
  return float(n/10)

'''
How to sum the digits:
First, we access the last digit by using Mod 10, which gives us the remainder
Second, in order to dispose of that digit (as we have already retrieved it), 
we divide the number by 10 and round down to the nearest integer. This is done by 
using math.floor(x)
Lastly, we add the retrieved digit to the recursive call of Summation that passes 
through the rounded-down, divided number
'''
def Summation(n):
  if n <= 0:
    return n
  else:
    print("---------------------")
    print("Number: ", n)
    print("Mod: ", n%10)
    print("Divide: ", str(n/10))
    print("New Num: ", math.floor(Divide(n)))
    return (n % 10) + Summation(math.floor(Divide(n)))

def Factorial(n):
  if n == 1:
    return n
  else:
    return n * Factorial(n-1)

def Main(n):
  return Summation(Factorial(n))

'''
To run the program: call Main(100). Then, on the first printed segment, compare 
Number to New Num. The only difference between these numbers is that New Num should 
have the last digit removed since we divided by 10 and got rid of the decimal. However, 
as you can see, the number changes drastically after this simple computation. If you 
scroll more towards the bottom, you can see this method work correctly.
'''

标签: pythonrecursion

解决方案


计算math.floor( n / 10 )转换为 64 位浮点数,然后再转换回整数。您应该将数字保留为整数。Python 中的整数具有无限的精度,因此它们可以表示 100 之类的数字!确切地。不可能代表100!完全是浮点数,而不使用更高精度的浮点数。

只需使用n // 10而不是math.floor(n / 10),避免转换。

您可以亲自了解如何在 Python 中工作///

>>> type(10)
<class 'int'>
>>> type(10/10)
<class 'float'>
>>> type(10//10)
<class 'int'>
>>> 10/10
1.0
>>> 10//10
1

推荐阅读