使用修正公式计算二项式系数时的错误答案

时间:2016-09-26 21:23:21

标签: python-2.7 math floating-point

我正在尝试使用以下公式编写一个函数来计算二项式系数:enter image description here

我遇到的问题是我无法得到正确的答案。这是我尝试编写函数的两种方法的示例。

def binomial(n, i):
    total = 0

    for j in range(1, (n-i+1)):
        n = float(n)
        i = float(i)
        j = float(j)        

        product = (i+j) / j

        if total == 0:
            total = product
        else:
            total = total * product

    print '%.f' %total

或者喜欢使用numpy

import numpy as np

def binomial_np(n, i):
    array = np.zeros(n-i+1)

    for j in range(1, (n-i+1)):
        s = float(j)
        n = float(n)
        i = float(i)

        array[j] = (i+s)/s

    array = array[1 : ]
    array = np.prod(array)    

    print '%.f' %array

这两个函数几乎都能产生正确的结果。在论坛上查看了一下后,我确实找到了一些确实产生正确结果的其他示例,例如来自Python Binomial Coefficient

的结果
import math
x = int(input("Enter a value for x: "))
y = int(input("Enter a value for y: "))
if y == x:
    print(1)
elif y == 1:         # see georg's comment
    print(x)
elif y > x:          # will be executed only if y != 1 and y != x
    print(0)
else:                # will be executed only if y != 1 and y != x and x <= y
    a = math.factorial(x)
    b = math.factorial(y)
    c = math.factorial(x-y)  # that appears to be useful to get the correct result
    div = a // (b * c)
    print(div) 

我从中得到的真正问题是,如果我编写公式的方式有问题,或者是否因为浮点数和小数位数在Python中的工作原理而无法以这种方式得到正确的答案。希望有人可以指出我正确的方向,我在这里做错了。

2 个答案:

答案 0 :(得分:1)

略微差异似乎来自使用浮点运算。但是,如果您确定idef binomial(n, i): result = 1 for j in range(1, n-i+1): result = result * (i+j) // j return result 是整数,那么您的例程中根本不需要浮点值。你可以做到

(i+j)/j

这是因为2个连续数的乘积可被1 * 2整除,3个连续数的乘积可被1 * 2 * 3整除,... ni连续数的乘积可被(ni)整除! 。上面代码中的计算被排序为只有整数结果,所以你得到一个确切的答案。这是因为我的代码不像您的代码那样计算result * (i+j);它计算j,然后除以n。这段代码也能很好地保持整数值尽可能小,这样可以提高速度。

如果当然,如果i0 <= i <= n是浮点而不是整数,则可能无效。另请注意,此代码不会检查if number < 5: print ("You have landed the bottle!") elif number < 10: print ("The bottle did not land, better luck next time.") else: print ("The bottle landed on the cap!") ,这应该完成。

答案 1 :(得分:0)

我确实会看到浮动精度是这里的主要问题。你做浮点除法,这意味着你的整数可能会四舍五入。我建议你将分子和分母保持为单独的数字,最后进行除法。或者,如果数字使用这种方法变得太大,请编写一些gcd计算并在此过程中取消常见因素。但只能进行整数除法(//)以避免精度损失。