这是一个位掩码 - 对于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之外,没有什么特别的30,所以这个查找实际上是在走你在开始之后立即通过Eratosthanes筛的掩模表示。你可以使用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位,所以这是一个小小的改进,但呃...几乎没有值得的麻烦。
所以这是更好的技巧之一,用于紧凑地存储合理的小素数。有趣的是,如果素数随机出现(但实际出现的相同数字达到1000000),则存储在1和10^6之间数字的素数中的信息量将是〜0.397比特因此,在天真的信息理论假设下,你会认为存储第一百万个素数的最好方法是使用1000000 * 0.397位或49609字节。)
应该是“每一个除了2,3和5之外的素数可以表示为...“? – MatrixFrog 2010-04-10 17:00:35
@MatrixFrog:当然,但是你的“解压程序”只会在输出压缩数据之前输出这3个数据。 – 2010-04-10 18:54:05