每个素数都可以表示为
30k±1
,30k±7
,30k±11
或 某些30k±13
k
。 这意味着我们每个可以使用8位 三十个数字来存储所有的 素数;一百万个素数可以 压缩到33,334字节
“这意味着我们可以使用每30位数8位来存储所有素数”
这个“每三十位八位”将用于 k ,对吗?但每个 k 值不一定只占用一位。不应该是 8 k值而是
“一百万个素数可以压缩到33,334字节”
我不确定这是怎么回事。
我们需要指出两件事:
k的值(可以任意大)
来自八个州(-13,-11,-7,-1,1,7,11,13)
我没有关注“33,334字节”到达的方式,但我可以说一件事:随着素数值越来越大,我们需要更多的空间来存储价值 k 。
如何,我们可以将其修复为“33,334字节”吗?
答案 0 :(得分:16)
这篇文章有点误导:我们不能存储100万个素数,但我们可以存储100万以下的所有素数。
k的值来自它在列表中的位置。对于这8个排列中的每一个,我们只需要1位(-13,-11 ..,11,13)
换句话说,我们将使用8位存储k = 0,8存储k = 1,8存储k = 2等。通过按顺序执行,我们不需要为每8位指定k的值 - 它只是前8位+ 1的值。
由于1,000,000 / 30 = 33,333 1/3,我们可以存储这些8位序列中的33,334来表示低于100万的值是素数,因为我们覆盖了k可以拥有的所有值,而没有30k-13超过限制100万。
答案 1 :(得分:11)
您无需存储k的每个值。如果要存储低于1百万的素数,请使用33,334字节 - 第一个字节对应于k = 0,第二个字节对应于k = 1等。然后,在每个字节中,使用1位表示“素数”或“复合” “为30k + 1,30k + 7等。
答案 2 :(得分:4)
它是一个位掩码 - 对于30个中可能为素数的8个值中的每个值都有一位,因此每30个数字为8位。要将所有素数列表为10 ^ 6,您需要8 * 10 ^ 6/30 = 2666667位= 33334字节。
要解释为什么这是一个好方法,你需要看看明显的替代方案。
更天真的方法就是使用位掩码。你需要一百万位,125000字节。
您还可以存储素数的值。高达1000000,这些值适合20位,并且有78498个素数,因此这给出了令人失望的1569960位(196245字节)。
另一种方法 - 虽然对查找素数不太有用 - 是存储每个素数和下一个素数之间的差异。在一百万以下,这适合6位(只要你记得那时的素数都是奇数,所以你只需要存储偶数差异就可以丢掉最低位),对于470998位== 58874字节。 (你可以通过计算你必须跳过多少mod-30插槽来削减另一部分。)
现在,除了30 = 2 * 3 * 5之外没有什么特别之处,所以这次查找实际上是在你刚开始之后通过位于Eratosthanes模式的Sieve的位掩码表示。你可以使用2 * 3 * 5 * 7 = 210,然后你必须考虑+ - 1,11,13,17,19,23,29,31,37,41,43,47,53, 59,61,67,71,73,79,83,89,97,101,103,48个值。如果你用7块30块来做这个,你需要7 * 8 = 56位,所以这是一个小小的改进,但是......几乎不值得麻烦。
所以这是一个更好的技巧,可以紧凑地存储相当小的素数。
(PS值得注意的是,如果素数随机出现(但实际出现的数字相同,则为1000000),存储在1到10 ^ 6之间的数字的素数中的信息量将为~0.397比特因此,在天真的信息理论假设下,您认为存储前一百万个素数的最佳方法是使用1000000 * 0.397位或49609个字节。)