【问题标题】:Python: Why do my 'if' statements' evaluate numbers incorrectly? [closed]Python:为什么我的“if”语句会错误地评估数字? [关闭]
【发布时间】:2018-12-21 18:44:49
【问题描述】:

代码如下:

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

请帮忙!

【问题讨论】:

  • 如果一个数不小于76.45,怎么可能小于12.1?
  • 如果你用笔和纸一步一步地按照自己的逻辑,这真的是你可以解决的问题。
  • 同样的事情措辞不同,小于 12.1 的数字总是小于 76.45。如果条件按顺序排列,为什么它不应该属于M?
  • 只是颠倒你的陈述顺序
  • 你需要按相反的顺序进行检查:如果小于0.0003,则为O型。否则,它可能仍小于0.13,在这种情况下为type乙等

标签: python if-statement logical-operators percentage


【解决方案1】:

如果您使用的是 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 &lt;= planetTypeChanceNum)。

但是,planetTypeChanceNum &gt;= 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)。

【讨论】:

  • 或者你使用带有权重和计数器的 random.choices() 让它更聪明:)
  • 啊,我还没有真正开始使用 Python 3(我知道,我知道,时钟在滴答作响),并且没有意识到 choices 现在开始使用权重了。
  • (哦,choices 是新的,与 choice 不同,但仍然如此。)
  • 是的,我只是参考你的回答。
【解决方案2】:

这就是你想要的:

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”的......

【讨论】:

  • 而我不明白的是为什么您仍然使用planetType = 'O'planetType = 'B' 等等而不使用它们
【解决方案3】:

你没有得到结果,因为后面的测试永远不可能是真的 - 前面的已经匹配了:

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()) 

输出(100 万颗星):

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

独库:


@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})

【讨论】:

  • 我想你想要cum_weights,而不是weights(这就是OP似乎拥有的)。
  • @chepner 相对权重(我给出的)被重新计算为累积权重 - 我可以通过直接将它们提供为 cum_weights 来避免该步骤,但随后来自 OP 的数字和我的数字之间的凝聚力消失了。 .. 还是您认为 M 的 % 是 M+K 的百分比...所以 M 的可能性比 K 小?
  • OP 正在生成一个介于 0 和 100 之间的随机数,但介于 0 和 12.1 之间的随机数不会产生 M 型行星,因此 M 型的权重仅为 76.45 - 12.1 = 64.35。我认为choices("OBAFGKMX", cum_weights=[0.0003, 0.013, ..., 12.1, 76.45, 100], k=numStars)会根据原始分布产生一组行星类型。
  • 我认为 OP 已经有了累积权重(至少,原始代码是这样对待它们的),所以没有必要自己计算它们。此外,您不必将值缩放为整数值; weightscum_weights 可以是 floats。 M,至少,看起来太高了(应该在 640,000 左右)。
  • 那是我的困惑;该结构意味着它们是累积的,只是顺序错误,但它们的总和确实接近于 1,它们可能是相对的(加上假设它们是相对的,就可以摆脱整个“其他 24% 呢”的问题) .
【解决方案4】:

你在滥用elif

除了 M 之外,您的任何案例都不会触发,因为一旦它们在 M if 块中“合格”,它们就会跳过 elifs。

要获得你想要的功能,你需要绑定你的 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 功能即可。

【讨论】:

  • elif 没问题,只要您按照适当的顺序进行检查。
  • 如果你按照我描述的那样做也可以。如果像 OP 那样使用就不好了
  • 如果条件详尽,您可能会进行冗余比较。
  • 我不确定 OP 是否真的处于那个水平,或者是否最小化计算或时间是他的问题的一部分
猜你喜欢
  • 2013-06-01
  • 1970-01-01
  • 2014-05-11
  • 1970-01-01
  • 2013-03-05
  • 2018-11-22
  • 2015-12-07
  • 2018-10-15
  • 1970-01-01
相关资源
最近更新 更多