目前正在研究一个素数计算器/检查器的解决方案。 algorythm已经工作并且非常有效(第一个9012330素数为0,359秒)。这是声明所有内容的上部区域的一部分:
const uint anz = 50000000;
uint a = 3, b = 4, c = 3, d = 13, e = 12, f = 13, g = 28, h = 32;
bool[,] prim = new bool[8, anz / 10];
uint max = 3 * (uint)(anz / (Math.Log(anz) - 1.08366));
uint[] p = new uint[max];
现在我想进入下一个级别并使用ulong而不是uint来覆盖更大的区域(你已经可以看到了),我点击了我的问题:bool-array。 就像每个人都应该知道的那样,bool有一个字节的长度,在创建数组时需要大量的内存......所以我正在寻找一种更加资源友好的方式来做到这一点。 我的第一个想法是一个位阵列 - >不是字节! < - 保存bool,但现在还没弄明白怎么做。所以如果有人做过这样的事情,我会很感激任何提示和解决方案。在此先感谢:)
答案 0 :(得分:2)
您可以使用BitArray集合: http://msdn.microsoft.com/en-us/library/system.collections.bitarray(v=vs.110).aspx
MSDN说明: 管理一个紧凑的位值数组,表示为布尔值,其中true表示该位为on(1),false表示该位为off(0)。
答案 1 :(得分:1)
您可以(并且应该)使用经过良好测试和熟知的库。
但是,如果您正在寻找学习的东西(就像看起来那样),您可以自己动手。
您可能想要使用自定义位阵列的另一个原因是使用硬盘驱动器来存储阵列,这在计算素数时非常有用。为此,您需要进一步拆分addr
,例如掩码的最低3位,接下来的28位用于256MB的内存存储,并从那里开始 - 缓冲文件的文件名
然而自定义位数组的另一个原因是在专门搜索质数时压缩内存使用。毕竟超过一半的比特将是“假”。因为与它们对应的数字是均匀的,所以实际上如果你甚至不存储偶数位,你既可以加速计算又可以减少内存需求。您可以通过更改addr
的解释方式来实现。此外,您还可以排除可被3整除的数字(每6个数字中只有2个有可能成为素数),因此与普通位数组相比,内存需求减少了60%。
请注意使用shift和逻辑运算符来提高代码效率。
例如, byte mask = (byte)(1 << (int)(addr & 7));
可以写成
byte mask = (byte)(1 << (int)(addr % 8));
和addr >> 3
可以写为addr / 8
测试shift / logical运算符vs division显示2.6s vs 4.8s,支持2000000次操作的shift / logical。
以下是代码:
void Main()
{
var barr = new BitArray(10);
barr[4] = true;
Console.WriteLine("Is it "+barr[4]);
Console.WriteLine("Is it Not "+barr[5]);
}
public class BitArray{
private readonly byte[] _buffer;
public bool this[long addr]{
get{
byte mask = (byte)(1 << (int)(addr & 7));
byte val = _buffer[(int)(addr >> 3)];
bool bit = (val & mask) == mask;
return bit;
}
set{
byte mask = (byte) ((value ? 1:0) << (int)(addr & 7));
int offs = (int)addr >> 3;
_buffer[offs] = (byte)(_buffer[offs] | mask);
}
}
public BitArray(long size){
_buffer = new byte[size/8 + 1]; // define a byte buffer sized to hold 8 bools per byte. The spare +1 is to avoid dealing with rounding.
}
}