【问题标题】:Mod function fails in python for large numbers对于大量数据,Mod 函数在 python 中失败
【发布时间】:2015-12-20 18:35:34
【问题描述】:

这个python代码

for x in range(20, 50):
    print(x,math.factorial(x),math.pow(2,x), math.factorial(x) % math.pow(2,x)  )

精确计算到 x=22,但当 x>22 时的 mod 始终为 0。

Wolframalpha 说 x>22 的结果是非零的。 例如,x=23 我们得到 6815744。

我猜这个问题是由 python 实际计算 mod 函数的方式引起的,但想知道是否有人真的知道。

【问题讨论】:

    标签: python-2.7 math


    【解决方案1】:

    您遇到了浮点限制; math.pow() 返回一个浮点数,因此两个操作数都被强制为浮点数。对于x = 23math.factorial(x) 返回一个大于浮点数可以建模的整数:

    >>> math.factorial(23)
    25852016738884976640000
    >>> float(math.factorial(23))
    2.585201673888498e+22
    

    右侧的运算符是一个小得多的浮点数(只有 7 位),正是指数的差异导致了模运算符错误。

    使用** 坚持整数:

    for x in range(20, 50):
        print(x, math.factorial(x), 2 ** x, math.factorial(x) % (2 ** x))
    

    整数运算只限于有多少内存可用,对于x = 23,计算出正确的值,一直正常工作到x = 49

    >>> x = 23
    >>> print(x, math.factorial(x), 2 ** x, math.factorial(x) % (2 ** x))
    23 25852016738884976640000 8388608 6815744
    >>> x = 49
    >>> print(x, math.factorial(x), 2 ** x, math.factorial(x) % (2 ** x))
    49 608281864034267560872252163321295376887552831379210240000000000 562949953421312 492581209243648
    

    请注意,即使对于较小的浮点模数计算,您确实应该使用math.fmod() function,原因在文档中进行了解释。但是,对于这种情况,它也失败了,因为您超出了浮点数学的限制:

    >>> print(x, math.factorial(x), math.pow(2, x), math.fmod(math.factorial(x), math.pow(2, x)))
    23 25852016738884976640000 8388608.0 0.0
    

    【讨论】:

    • 感谢您的解决方案,尽管我对您的陈述感到困惑“右侧运算符是一个小得多的浮点数(只有 9 位)”哪 9 位?
    • @aquagremlin: 8388608.0,这是 7。哎呀。
    • 这段代码也给出了一个有趣的情节,没有错误%matplotlib inline import numpy as np import matplotlib.pyplot as plt import scipy.misc x = np.linspace(0, 5, 70) plt.plot(scipy.misc.factorial(x) % np.power(2,x)) plt.show()
    • numpy 应该会出错,事实上它比 math.pow 更快,那么为什么这个情节有效?
    • @aquagremlin:np.power() 为整数输入返回一个整数,scipy.misc.factorial() 默认返回一个整数。此外,numpy 数组重载了 % 运算符以应用于单个元素,因此如果他们愿意,它们可以以不同于核心 Python 的方式实现它。
    【解决方案2】:

    是的,你对大数是正确的,模数给出了错误的数字,尤其是阶乘数字。

    例如:

    import math
    
    def comb(n,r):
        res= math.factorial(n)/(math.factorial(n-r)*math.factorial(r))
        return(float(res))
        
    sum1=0
    num=888
    
    for r in range(0,num+1):
        sum1 +=comb(num,r)
        
    
        
    print(sum1 % 1000000)
    

    给出错误答案 252480 但正确答案是 789056。

    【讨论】:

      猜你喜欢
      • 2014-06-06
      • 2021-08-04
      • 2021-12-12
      • 1970-01-01
      • 2020-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多