请原谅我初学者的错误:) 我有一项任务要求我找到用户输入的彩票球总数和抽奖球数量的概率。我的代码很可能也有其他问题,但我无法克服表示 n 未定义的错误代码。这就是我所拥有的:
import math
def winning(n, p):
"""Find the probability of guessing all balls correct"""
a = math.factorial(n)/(math.factorial(n - p) * math.factorial(p))
b = 1/a
return b
win = winning(n, p)
def main():
n = int(input("Enter the total number of lottery balls:", ))
# number of balls
p = int(input("Enter the number of the drawn balls:", ))
# number of balls drawn
if p > n:
print("At most the total number of balls can be drawn.")
if n < 1:
print("The number of balls must be a positive number.")
else:
print("The probability of guessing all", p, "balls correctly is", win)
main()
另外, math.factorial() 是在 Python 中使用阶乘的有效方法还是我应该使用其他方法?
您在未事先定义 n 或 p 的情况下调用 Winning(n, p)。正如 Tim 提到的,将您对 wining(n, p) 的调用移至 main() 定义之后意味着它在用户声明 n 和 p 之后被调用。
例如以下内容会产生错误:
def sum(a, b):
return (a + b)
sum(a, b)
a = int(input('Enter 1st number: '))
b = int(input('Enter 2nd number: '))
而以下情况则不然:
def sum(a, b):
return (a + b)
a = int(input('Enter 1st number: '))
b = int(input('Enter 2nd number: '))
sum(a, b)
math.comb
来计算二项式系数而不是手动计算:
lottery_probability.py
:
"""Lottery Probability Calculator."""
import math
import sys
import numpy as np
def get_lottery_coverage(total_balls: int, balls_drawn: int) -> int:
return math.comb(total_balls, balls_drawn)
def get_int_input(prompt: str) -> int:
while True:
try:
return int(input(prompt))
except ValueError:
print('Error: Enter a integer, try again...')
def main() -> None:
print('Lottery Probability Calculator')
print('==============================')
total_balls = get_int_input('Enter the total number of lottery balls: ')
if total_balls < 1:
print('Error: The number of lottery balls must be a positive number.')
sys.exit(1)
balls_drawn = get_int_input('Enter the number of balls drawn: ')
if balls_drawn < 1:
print('Error: The number of balls drawn must be a positive number.')
sys.exit(1)
if balls_drawn > total_balls:
print(f'Error: At most {total_balls} can be drawn.')
sys.exit(1)
print(
f'The probability of guessing all {balls_drawn} balls correctly from '
f'{total_balls} is:'
)
lottery_coverage = get_lottery_coverage(total_balls, balls_drawn)
win_probability = 1 / lottery_coverage
win_probability_percentage = win_probability * 100
print(f'{np.format_float_positional(win_probability, trim="-")}')
print('or')
print(f'{np.format_float_positional(win_probability_percentage, trim="-")}%')
print('or')
print(f'1 in {get_lottery_coverage(total_balls, balls_drawn):,}')
if __name__ == '__main__':
main()
用法示例:
Lottery Probability Calculator
==============================
Enter the total number of lottery balls: 49
Enter the number of balls drawn: 6
The probability of guessing all 6 balls correctly is:
0.00000007151123842018516
or
0.000007151123842018516%
or
1 in 13,983,816
lottery_probability_test.py
:
"""Tests for Lottery Probability Calculator."""
import io
import textwrap
import unittest
from unittest import mock
import lottery_probability
class MainTest(unittest.TestCase):
@mock.patch('builtins.input', side_effect=['49', '6'])
@mock.patch('sys.stdout', new_callable=io.StringIO)
def test_running_main_valid_input_prints_to_stdout(self, mock_stdout, _):
lottery_probability.main()
self.assertEqual(
mock_stdout.getvalue(),
textwrap.dedent("""\
Lottery Probability Calculator
==============================
The probability of guessing all 6 balls correctly from 49 is:
0.00000007151123842018516
or
0.000007151123842018516%
or
1 in 13,983,816
"""),
)
@mock.patch('builtins.input', side_effect=['a', '49.5', '49', '6'])
@mock.patch('sys.stdout', new_callable=io.StringIO)
def test_invalid_int_requires_reinput(self, mock_stdout, _):
lottery_probability.main()
self.assertContainsExactSubsequence(
mock_stdout.getvalue(),
textwrap.dedent("""\
Error: Enter a integer, try again...
Error: Enter a integer, try again...
"""),
)
@mock.patch('builtins.input', side_effect=['0', '6'])
@mock.patch('sys.stdout', new_callable=io.StringIO)
def test_total_balls_less_than_one_gives_error(self, mock_stdout, _):
with self.assertRaises(SystemExit) as cm:
lottery_probability.main()
self.assertEqual(cm.exception.code, 1)
self.assertContainsExactSubsequence(
mock_stdout.getvalue(),
'Error: The number of lottery balls must be a positive number.',
)
@mock.patch('builtins.input', side_effect=['6', '0'])
@mock.patch('sys.stdout', new_callable=io.StringIO)
def test_balls_drawn_less_than_one_gives_error(self, mock_stdout, _):
with self.assertRaises(SystemExit) as cm:
lottery_probability.main()
self.assertEqual(cm.exception.code, 1)
self.assertContainsExactSubsequence(
mock_stdout.getvalue(),
'Error: The number of balls drawn must be a positive number.',
)
@mock.patch('builtins.input', side_effect=['49', '50'])
@mock.patch('sys.stdout', new_callable=io.StringIO)
def test_balls_drawn_more_than_total_balls_gives_error(self, mock_stdout, _):
with self.assertRaises(SystemExit) as cm:
lottery_probability.main()
self.assertEqual(cm.exception.code, 1)
self.assertContainsExactSubsequence(
mock_stdout.getvalue(),
'Error: At most 49 can be drawn.',
)
if __name__ == '__main__':
unittest.main()