我正在编写一个Python脚本来为心算训练生成问题。加法和乘法很容易,但我在试图为减法问题产生无偏见的问题时遇到了麻烦。
我希望能够指定minuend(第一个数字)的最小值和最大值 - 例如,对于两位数的减法,它应该在20到99之间。减数还应该有一个范围选项( 11-99,说)。答案需要是积极的,最好还是以这种情况下的最低限度为10。
所以:
当然,所有数值都应该用作变量。
我满足以下条件:
ansMin, ansMax = 10, 99
subtrahendMin, minuendMax = 11,99
# the other max and min did not seem to be necessary here,
# and two ranges was the way I had the program set up
answer = randint(ansMin, ansMax)
subtrahend = randint(subtrahendMin, minuendMax - answer)
minuend = answer + subtrahend # rearranged subtraction equation
这里的问题是,minuend值几乎全部超过50,因为答案和减数首先生成并加在一起,只有它们在范围的底部25%的部分才会得到结果低于50%。 (编辑:这不是严格正确的 - 例如,底部1%加上底部49%会起作用,百分比无论如何都是描述它的坏方法,但我认为这个想法很明确。)
我还考虑过尝试完全随机生成minuend和subtrahend值,然后如果它与标准不匹配则抛出答案(即,minuend大于subtrahend的值至少大于answerMin并且他们都符合上面列出的标准),但我认为这会导致类似的偏见。
我并不关心它完美,但这太过分了。我希望minuend值在允许范围内是完全随机的,并且减数值在minuends允许的范围内随机变化(如果我正确地考虑它,这将偏向于较低的那些)。我不认为我真的关心答案的分布(只要它不是荒谬的偏见)。有没有更好的方法来计算这个?
答案 0 :(得分:2)
在这种情况下,有几种方法可以定义“没有偏见”的含义。我假设您正在寻找的是从允许的问题空间中以相等的概率选择每个可能的减法问题。快速而肮脏的方法:
请注意粗体部分。如果仅丢弃y并保留x,则问题将在x中均匀分布,而不是在整个问题空间中。你需要确保每个有效的x至少有一个有效的y - 原来选择的范围不是这种情况,我们稍后会看到。
现在是漫长而恰当的方法。首先,我们需要找出问题空间的实际大小。
允许的减数集由minuend决定:
x in [21, 99]
y in [11, x-10]
或使用符号常量:
x in [x_min, x_max]
y in [y_min, x - answer_min]
我们可以将其重写为
x in [21, 99]
y = 11 + a
a in [0, x-21]
或再次使用符号常量
x in [x_min, x_max]
y = y_min + a
a in [0, x - (answer_min + y_min)].
由此可见,只有x> =(answer_min + y_min)才存在有效问题,对于给定的x,有x - (answer_min + y_min)+ 1个可能的子路径。
现在我们假设x_max不会施加任何进一步的约束,例如那个answer_min + y_min> = 0:
x in [21, 99], number of problems:
(99 - 21 + 1) * (1 + 78+1) / 2
x in [x_min, x_max], number of problems:
(x_max - x_min + 1) * (1 + x_max - (answer_min + y_min) + 1) / 2
使用算术序列之和的公式获得上述内容。因此,您需要选择[1,4740]范围内的随机数。要将此数字转换为减法问题,我们需要定义问题空间和整数之间的映射。示例映射如下:
等等。请注意,当超过三角形数字时,x会跳过1。为了从随机数r计算x和y,最好通过在预先计算的表中搜索来找到大于或等于r的最低三角形数t;将此数字写为q *(q + 1)/ 2。然后x = x_min + q-1和y = y_min + t - r。
完成计划:
import random
x_min, x_max = (21, 99)
y_min = 11
answer_min = 10
triangles = [ (q*(q+1)/2, q) for q in range(1, x_max-x_min+2) ]
upper = (x_max-x_min+1) * (1 + x_max - (answer_min + y_min) + 1) / 2
for i in range(0, 20):
r = 1 + random.randrange(0, upper)
(t, q) = next(a for a in triangles if a[0] >= r)
x = x_min + q - 1
y = y_min + t - r
print "%d - %d = ?" % (x, y)
请注意,对于大多数问题(大约75%),x将大于60.这是正确的,因为对于较小的minuend值,减数的允许值较少。
答案 1 :(得分:0)
我可以看到你的起始值有几个问题 - 如果你想让答案总是大于10 - 那么你需要增加MinuendMin,或者减少SubtrahendMin因为20-11小于10 ...你已经将答案min和max定义为3,9 - 这意味着答案永远不会超过10 ......
除此之外,我通过首先选择minuend值,然后根据它和answerMin选择减数值,设法得到一个很好的均匀分布值:
ansMin = 10
minuendMin, minuendMax = 20,99
subtrahendMin = 9;
minuend = randint(minuendMin, minuendMax )
subtrahend = randint(subtrahendMin,(minuend-ansMin) )
answer = minuend - subtrahend
答案 2 :(得分:0)
你说你已经有额外的工作正常了。假设您对加数/总和有类似的限制,您可以重新排列因子,以便:
minuend <= sum
subtrahend <= first addend
answer <= second addend
如果需要,可以对乘法/除法进行类似的映射。