Arithmetic error: Python is incorrectly dividing variables
Arithmetic error: Python is incorrectly dividing variables
我得到了一些似乎没有多大意义的东西。我正在通过编写一个小程序来练习我的编码,该程序可以让我有可能在纸牌游戏的特定时间范围内获得某些纸牌。为了计算机会,我需要创建一个方法来执行除法,并将机会报告为分数和小数。所以我设计了这个:
from fractions import Fraction
def time_odds(card_count,turns,deck_size=60):
chance_of_occurence = float(card_count)/float(deck_size)
opening_hand_odds = 7*chance_of_occurence
turn_odds = (7 + turns)*chance_of_occurence
print ("Chance of it being in the opening hand: %s or %s" %(opening_hand_odds,Fraction(opening_hand_odds)))
print ("Chance of it being acquired by turn %s : %s or %s" %(turns,turn_odds,Fraction(turn_odds) ))
然后我像这样使用它:
time_odds(3,5)
但无论出于何种原因,我得到了这个作为答案:
"Chance of it being in the opening hand: 0.35000000000000003 or
6305039478318695/18014398509481984"
"Chance of it being acquired by turn 5 : 0.6000000000000001 or
1351079888211149/2251799813685248"
所以这几乎是正确的,只是小数点略有偏差,给出了 0.0000000000003 的差异或 0.000000000000000000001 的差异。
Python 当我让它像这样进行除法时不会这样做:
print (7*3/60)
这只给我 0.35,这是正确的。我能观察到的唯一区别是,当我除以变量而不仅仅是数字时,我得到的值稍微不正确。
我四处寻找答案,大多数不正确的除法问题都与整数除法有关(或者我认为它可以称为底除法),但我没有找到任何解决这个问题的方法.
当我对非常大的数字进行除法时,python 遇到了类似的问题。怎么回事?
为什么会这样?我该怎么做才能纠正它?
您看到的额外数字是浮点精度错误。随着您对浮点数进行越来越多的运算,错误有可能会复合。
当您尝试手动复制计算时看不到它们的原因是您的复制以不同的顺序执行操作。如果你计算 7 * 3 / 60
,乘法首先发生(没有错误),并且除法引入了一个足够小的错误,Python 的 float
类型将它隐藏在它的 [=14] 中=](因为 0.35
明确指代与计算相同的浮点值)。如果你做 7 * (3 / 60)
,除法首先发生(引入错误)然后乘法将错误的大小增加到无法隐藏的程度(因为 0.35000000000000003
是一个不同的浮点值0.35
).
为避免打印出可能出错的额外数字,您可能需要明确指定将数字转换为字符串时要使用的精度。例如,与其使用 %s
格式代码(在值上调用 str
),您可以使用 %.3f
,它将在小数点后三位四舍五入。
您的 Fraction
有另一个问题。您正在直接从浮点值创建 Fraction
,该值已经计算出错误。这就是为什么您看到分数用非常大的分子和分母打印出来(它完全代表与不准确的浮动)。如果您改为将整数分子和分母值传递给 Fraction
构造函数,它将负责为您简化分数而不会出现任何浮点数错误:
print("Chance of it being in the opening hand: %.3f or %s"
% (opening_hand_odds, Fraction(7*card_count, deck_size)))
这应该将数字打印为 0.350
和 7/20
。你当然可以选择你想要的小数位数。
与浮点错误完全分开,计算实际上并没有得到正确的概率。您正在使用的公式可能足以让您在玩游戏时在脑海中进行计算,但它并不完全准确。如果您正在使用计算机为您计算数字,您不妨做对。
在 D
次抽牌后,从大小为 M
的牌组中抽到至少一张 N
特定牌的概率是:
1 - (comb(M-N, D) / comb(M, D))
其中comb
是二元系数或"combination"函数(数学上常说成"N choose R",写作"nCr")。 Python 在标准库中没有该函数的实现,但是您可能已经安装了很多附加模块来提供一个,或者您可以很容易地编写自己的模块。有关详细信息,请参阅 this earlier question。
对于您的示例参数,正确的赔率是“5397/17110”或 0.315
。
我得到了一些似乎没有多大意义的东西。我正在通过编写一个小程序来练习我的编码,该程序可以让我有可能在纸牌游戏的特定时间范围内获得某些纸牌。为了计算机会,我需要创建一个方法来执行除法,并将机会报告为分数和小数。所以我设计了这个:
from fractions import Fraction
def time_odds(card_count,turns,deck_size=60):
chance_of_occurence = float(card_count)/float(deck_size)
opening_hand_odds = 7*chance_of_occurence
turn_odds = (7 + turns)*chance_of_occurence
print ("Chance of it being in the opening hand: %s or %s" %(opening_hand_odds,Fraction(opening_hand_odds)))
print ("Chance of it being acquired by turn %s : %s or %s" %(turns,turn_odds,Fraction(turn_odds) ))
然后我像这样使用它:
time_odds(3,5)
但无论出于何种原因,我得到了这个作为答案:
"Chance of it being in the opening hand: 0.35000000000000003 or
6305039478318695/18014398509481984"
"Chance of it being acquired by turn 5 : 0.6000000000000001 or
1351079888211149/2251799813685248"
所以这几乎是正确的,只是小数点略有偏差,给出了 0.0000000000003 的差异或 0.000000000000000000001 的差异。
Python 当我让它像这样进行除法时不会这样做:
print (7*3/60)
这只给我 0.35,这是正确的。我能观察到的唯一区别是,当我除以变量而不仅仅是数字时,我得到的值稍微不正确。
我四处寻找答案,大多数不正确的除法问题都与整数除法有关(或者我认为它可以称为底除法),但我没有找到任何解决这个问题的方法.
当我对非常大的数字进行除法时,python 遇到了类似的问题。怎么回事?
为什么会这样?我该怎么做才能纠正它?
您看到的额外数字是浮点精度错误。随着您对浮点数进行越来越多的运算,错误有可能会复合。
当您尝试手动复制计算时看不到它们的原因是您的复制以不同的顺序执行操作。如果你计算 7 * 3 / 60
,乘法首先发生(没有错误),并且除法引入了一个足够小的错误,Python 的 float
类型将它隐藏在它的 [=14] 中=](因为 0.35
明确指代与计算相同的浮点值)。如果你做 7 * (3 / 60)
,除法首先发生(引入错误)然后乘法将错误的大小增加到无法隐藏的程度(因为 0.35000000000000003
是一个不同的浮点值0.35
).
为避免打印出可能出错的额外数字,您可能需要明确指定将数字转换为字符串时要使用的精度。例如,与其使用 %s
格式代码(在值上调用 str
),您可以使用 %.3f
,它将在小数点后三位四舍五入。
您的 Fraction
有另一个问题。您正在直接从浮点值创建 Fraction
,该值已经计算出错误。这就是为什么您看到分数用非常大的分子和分母打印出来(它完全代表与不准确的浮动)。如果您改为将整数分子和分母值传递给 Fraction
构造函数,它将负责为您简化分数而不会出现任何浮点数错误:
print("Chance of it being in the opening hand: %.3f or %s"
% (opening_hand_odds, Fraction(7*card_count, deck_size)))
这应该将数字打印为 0.350
和 7/20
。你当然可以选择你想要的小数位数。
与浮点错误完全分开,计算实际上并没有得到正确的概率。您正在使用的公式可能足以让您在玩游戏时在脑海中进行计算,但它并不完全准确。如果您正在使用计算机为您计算数字,您不妨做对。
在 D
次抽牌后,从大小为 M
的牌组中抽到至少一张 N
特定牌的概率是:
1 - (comb(M-N, D) / comb(M, D))
其中comb
是二元系数或"combination"函数(数学上常说成"N choose R",写作"nCr")。 Python 在标准库中没有该函数的实现,但是您可能已经安装了很多附加模块来提供一个,或者您可以很容易地编写自己的模块。有关详细信息,请参阅 this earlier question。
对于您的示例参数,正确的赔率是“5397/17110”或 0.315
。