我得到的东西似乎并没有多大意义。我正在练习我的编码,通过制作一个小程序,让我有可能在纸牌游戏的特定时间范围内获得某些卡片。为了计算机会,我需要创建一个执行除法的方法,并将机会报告为分数和小数。所以我设计了这个:
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类似的问题。发生了什么事?
为什么会这样?我该怎么做才能纠正它?
答案 0 :(得分:3)
您看到的额外数字是浮点精度错误。当您使用浮点数进行越来越多的操作时,错误有可能复合。
当您尝试手动复制计算时,您没有看到它们的原因是您的复制以不同的顺序执行操作。如果你计算7 * 3 / 60
,则首先发生重复数据删除(没有错误),并且除法会引入一个足够小的错误,Python float
类型会在repr
中为你隐藏它(因为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
。您当然可以选择任意数量的小数位。
完全与浮点错误分开,计算实际上没有正确的概率。你正在使用的公式可能足以让你在玩游戏时做到这一点,但它并不完全准确。如果您正在使用计算机来为您处理数字,那么您也可以做对。
在N
抽取后,从M
尺寸的牌组中抽取至少一张D
张特定牌的概率为:
1 - (comb(M-N, D) / comb(M, D))
其中comb
是二进制系数或"组合"功能(通常用" N选择R"和写'&34; nCr"在数学中)。 Python在标准库中没有该函数的实现,但是你可能已经安装了很多可以提供的模块,或者你可以很容易地编写自己的模块。有关详细信息,请参阅this earlier question。
对于您的示例参数,正确的赔率是“5397”/ 17110'或0.315
。