【发布时间】:2014-01-09 10:11:36
【问题描述】:
在python docs 中,“set.pop() 从 s 中删除并返回任意元素”。在生成一些随机数据来测试程序时,我注意到这个 pop() 函数的奇怪行为。这是我的代码(python 2.7.3):
testCases = 10
numberRange = 500
poppedValues = []
greaterPercentages = []
for i in range (testCases):
s = Set()
""" inserting 100 random values in the set, in the range [0, numberRange) """
for j in range (100):
s.add(random.randrange(numberRange))
poppedValue = s.pop()
greaterCount = 0
""" counting how many numbers in the set are smaller then the popped value """
for number in s:
if poppedValue > number:
greaterCount += 1
poppedValues.append(poppedValue)
greaterPercentages.append(float(greaterCount) / len(s) * 100)
for poppedValue in poppedValues:
print poppedValue, '\t',
print
for percentage in greaterPercentages:
print "{:2.2f}".format(percentage), '\t',
我在这里做的是,
- 在集合
s中插入一些随机值,其中每个元素都在 [0,numberRange) 范围内 - 从集合中弹出一个元素(根据文档,它应该是随机的)
- 计算集合中有多少元素小于弹出的值
我预计弹出的值应该是随机的,并且集合中大约 50% 的数字将大于弹出的值。但似乎pop() 几乎总是返回集合中的最小数字。这是numberRange = 500 的结果。第一行表示弹出元素的值。第二行是小于弹出值的元素的百分比。
9 0 3 1 409 0 1 2 4 0
0 % 0 % 0 % 0 % 87 % 0 % 0 % 0 % 0 % 0 %
我使用不同的 numberRange 值进行了此测试。似乎对于集合元素的较低值,pop() 几乎总是返回最低元素。但是对于更高的值,它会返回一个随机元素。对于numberRange = 1000,结果为:
518 3586 3594 4103 2560 3087 4095 3079 3076 1622
7 % 72 % 73 % 84 % 54 % 51 % 79 % 63 % 67 % 32 %
我认为这是非常随机的。为什么会有这种奇怪的行为?我做错了吗?
编辑:感谢大家的回答和评论,看来“随意”,不能保证一定是“随机”。
【问题讨论】:
-
不是随机的,是无序的。
-
文档中的“任意”并不意味着“随机”,它们的意思是“不依赖任何特定值,实现细节可能会在没有警告的情况下更改”
-
随机并不意味着它分布得很好,甚至是不可预测的。这意味着您不能依赖任何观察来判断未来是否正确。
-
是的,恕我直言,
random.choice(s)不适用于集合。此外,random.choice对于 dicts 来说完全是 BROKEN,see here for more details about that。 -
@wim:同意,如果有人刚刚阅读了
random文档并且不理解 Python/C++ 术语“序列”,那么set或 @987654337 并不明显@不是一个。我对“序列”、“可迭代”、“迭代器”等术语在 Python 文档的各个部分中被假定为词汇表这一事实并不强烈,但毫无疑问,它至少会吸引大多数人一次。另外,如果random.choice在任意可迭代(在O(n)时间和O(1)内存中)以及在任何时间复杂度可行的集合和字典上工作,那就太好了。