Python:为什么我的“ if”语句对数字的评估不正确?

时间:2018-12-21 18:44:50

标签: python if-statement logical-operators percentage

代码如下:

from random import *

numStars = int(input("Number of stars: ").strip())

planetTypeDict = {'O':0, 'B':0, 'A':0, 'F':0, 'G':0, 'K':0, 'M':0}

for star in range (numStars):
    planetTypeChanceNum =  uniform (0, 100)

    if planetTypeChanceNum < 76.45:
        planetType = 'M'
        planetTypeDict['M'] += 1

    elif planetTypeChanceNum < 12.1:
        planetType = 'K'
        planetTypeDict['K'] += 1

    elif planetTypeChanceNum < 7.6:
        planetType = 'G'
        planetTypeDict['G'] += 1

    elif planetTypeChanceNum < 3:
        planetType = 'F'
        planetTypeDict['F'] += 1

    elif planetTypeChanceNum < 0.6:
        planetType = 'A'
        planetTypeDict['A'] += 1

    elif planetTypeChanceNum < 0.13:
        planetType = 'B'
        planetTypeDict['B'] += 1

    elif planetTypeChanceNum < 0.0003:
        planetType = 'O'
        planetTypeDict['O'] += 1

print(planetTypeDict)

问题是代码输出大约75%的“ M”星,除此之外没有其他东西。例如,当我使用1000作为numStars的值时,得到的结果约为:

{'O': 241, 'B': 0, 'A': 0, 'F': 0, 'G': 0, 'K': 0, 'M': 759}

我已尽力解决此错误,包括将逻辑更改为:

if planetTypeChanceNum > 100 - 'chance here':
    # stuff

请帮助!

4 个答案:

答案 0 :(得分:2)

如果您使用的是Python 3,请使用random.choices,如Patrick Artner所示。

否则,只需颠倒检查顺序:

if planetTypeChanceNum < 0.0003:
    planetType = 'O'
elif planetTypeChanceNum < 0.13:
    planetType = 'B'
elif planetTypeChanceNum < 0.6:
    planetType = 'A'
elif planetTypeChanceNum < 3:
    planetType = 'F'
elif planetTypeChanceNum < 7.6:
    planetType = 'G'
elif planetTypeChanceNum < 12.1:
    planetType = 'K'
elif planetTypeChanceNum < 76.45:
    planetType = 'M'

planetTypeDict[planetType] += 1

如果第一次检查失败,则planetTypeChanceNum仍可以小于0.13(暗示0.0003 <= planetTypeChanceNum)。

但是,planetTypeChanceNum >= 76.45是什么类型的行星?如果缺少else子句,或者缺少最初的if语句,如果在这种情况下根本没有行星,则会提早继续循环。

if planetTypeChanceNum < 0.0003:
    planetType = 'O'
elif planetTypeChanceNum < 0.13:
    planetType = 'B'
elif planetTypeChanceNum < 0.6:
    planetType = 'A'
elif planetTypeChanceNum < 3:
    planetType = 'F'
elif planetTypeChanceNum < 7.6:
    planetType = 'G'
elif planetTypeChanceNum < 12.1:
    planetType = 'K'
elif planetTypeChanceNum < 76.45:
    planetType = 'M'
else:
    planetType = ???

if planetType >= 76.45:
    # No planet at all
    continue
elif planetTypeChanceNum < 0.0003:
    planetType = 'O'
elif planetTypeChanceNum < 0.13:
    planetType = 'B'
elif planetTypeChanceNum < 0.6:
    planetType = 'A'
elif planetTypeChanceNum < 3:
    planetType = 'F'
elif planetTypeChanceNum < 7.6:
    planetType = 'G'
elif planetTypeChanceNum < 12.1:
    planetType = 'K'
elif planetTypeChanceNum < 76.45:
    planetType = 'M'

这两个都将彻底覆盖间隔[0,100)。

答案 1 :(得分:1)

这就是您想要的:

if planetTypeChanceNum < 0.0003:
    planetType = 'O'
    planetTypeDict['O'] += 1
elif planetTypeChanceNum < 0.13:
    planetType = 'B'
    planetTypeDict['B'] += 1
elif planetTypeChanceNum < 0.6:
    planetType = 'A'
    planetTypeDict['A'] += 1
elif planetTypeChanceNum < 3:
    planetType = 'F'
    planetTypeDict['F'] += 1
elif planetTypeChanceNum < 12.1:
    planetType = 'K'
    planetTypeDict['K'] += 1
elif planetTypeChanceNum < 76.45:
    planetType = 'M'
    planetTypeDict['M'] += 1

我想知道的是您如何用原始代码获得任何“ O” ...

答案 2 :(得分:1)

您没有得到结果,因为以后的测试永远不可能是正确的-前面的测试已经匹配:

if a < 10:
    pass  # this eats up a=0,1,2,3,4,...,9  
elif a < 5:
    pass  # never gonna happen.

此外,您可以通过使用random.choices()为每个选择提供权重并使用Counter来对其进行计数来简化创建工作:

from random import choices
from collections import Counter

numStars = int(input("Number of stars: ").strip())

planetTypeDict = Counter({'O':0, 'B':0, 'A':0, 'F':0, 'G':0, 'K':0, 'M':0})

# https://docs.python.org/3/library/random.html#random.choices

# these weights are relative weights, meaning:
# M: 76.45 %
# K: 12.10 %
# G:  7.60 %
# F:  3.00 %
# A:  0.60 %
# B:  0.13 %
# O:  0.0003 %
# others - the rest of planet types (as the former do not add up to 100%)

types = [ "M","K","G","F","A","B","O", "other"] 
w     = [ 764500, 121000, 76000, 30000, 6000, 1300, 3, 
          1000000-sum( [764500, 121000, 76000, 30000, 6000, 1300, 3])]

planetTypeDict.update(choices(types,weights=w,k=numStars))
print(planetTypeDict.most_common()) 

输出(一百万颗星):

Number of stars: [('M', 763764), ('K', 121696), ('G', 75998), ('F', 29970), 
                  ('A', 6147), ('B', 1247), ('other', 1175), ('O', 3)]

Doku:


@Chepner指出,您的权重可能已经累积,考虑到if的结构:

print(Counter(choices("OBAFGKMX", cum_weights=[0.0003 ,0.13 ,0.6 ,3 ,7.6 ,12.1,
                                               76.45 ,100], k=1000000)))

通往:

Counter({'M': 643289, 'X': 235341, 'G': 45979, 'K': 45262, 'F': 24032, 'A': 4768, 'B': 1324, 'O': 5})

答案 3 :(得分:0)

您滥用elif

除了M之外,您的所有案例都不会触发,因为一旦它们在M if块处“合格”,便会跳过省略号。

要获得所需的功能,您需要绑定if语句,而不是单方面。

示例:

if 12.1 < planetTypeChanceNum < 76.45:
        planetType = 'M'
        planetTypeDict['M'] += 1
elif 7.6 < planetTypeChanceNum < 12.1:
        planetType = 'K'
        planetTypeDict['K'] += 1

有更有效的方法来执行此操作,但是我认为此时您只需要了解if / elif功能。