【问题标题】:Python not correctly dividing large floatsPython 没有正确划分大浮点数
【发布时间】:2021-06-13 23:47:00
【问题描述】:

我正在编写一个程序来计算 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) 不能正确除法。

Here is the output when I run using 100 as an input. The first line is the calculated factorial, Mod is the last digit, Divide is the factorial divided by 10 (not rounded), and New Num is the rounded down value. As you can see, New Num was not accurately divided

这里的大问题是,是什么让这个计算在如此高的值下不正确?这是否与 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.
'''

【问题讨论】:

  • 不要使用float。只需使用为此量身定制的整数,因为 Python 整数可以任意大。您根本不需要导入math。使用整数除法(// 运算符)和 mod(% 运算符)。

标签: python recursion


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    使用floor(x/10) 将首先将x/10 计算为浮点数。浮点数只有 53 位有效位的精度,因此它们无法正确处理大量数字。处理大数时,最好坚持使用整数运算。替换:

    floor(x / 10)  --->  x // 10
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多