How can I test for primality?

前端 未结 16 2186
南方客
南方客 2020-12-05 08:29

I am writing a little library with some prime number related methods. As I\'ve done the groundwork (aka working methods) and now I\'m looking for some optimization. Ofcours

16条回答
  •  庸人自扰
    2020-12-05 08:47

    Repeat mode operations will run very slowly. Use the eratosthenes grid to get the prime list in order.

    /*
    The Sieve Algorithm
    http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
    */
    numbers = new MyBitArray(limit, true);
    for (long i = 2; i < limit; i++)
        if (numbers[i])
            for (long j = i * 2; j < limit; j += i)
                numbers[j] = false;
            }
    
    public class MyBitArray: IDisposable
        {
            byte[] bytes;
            public MyBitArray(long limit, bool defaultValue = false)
            {
                long byteCount = (limit & 7) == 0 ? limit >> 3 : (limit >> 3) + 1;
                this.bytes = new byte[byteCount];
                for(long i = 0; i < byteCount; i++)
                {
                    bytes[i] = (defaultValue == true ? (byte)0xFF : (byte)0x00);
                }
                this.limit = limit;
            }
    
            public MyBitArray(long limit, byte[] bytes)
            {
                this.limit = limit;
                this.bytes = bytes;
            }
    
            public bool this[long index]
            {
                get
                {
                    return getValue(index);
                }
                set
                {
                    setValue(index, value);
                }
            }
            
            bool getValue(long index)
            {
                if (index < 8)
                {
                    return getBit(bytes[0], (byte)index);
                }
    
                long byteIndex = (index & 7) == 0 ? ((index >> 3) - 1) : index >> 3;
                byte bitIndex = (byte)(index & 7);
                return getBit(bytes[byteIndex], bitIndex);
            }
            void setValue(long index, bool value)
            {
                if (index < 8)
                {
                    bytes[0] = setBit(bytes[0], (byte)index, value);
                    return;
                }
    
                long byteIndex = (index & 7) == 0 ? (index >> 3) - 1 : index >> 3;
                byte bitIndex = (byte)(index & 7);
                
                bytes[byteIndex] = setBit(bytes[byteIndex], bitIndex, value);
            }
    
            bool getBit(byte byt, byte index)
            {
                return ((byt & (1 << index)) >> index) == 1;
            }
    
            byte setBit(byte byt, byte index, bool value)
            {
                return (byte)((byt & ~(1 << index)) + (value ? 1 << index : 0));
            }
    
            public void Dispose()
            {
                GC.Collect(2, GCCollectionMode.Optimized);
            }
    
            private long limit;
            public long Limit { get { return limit; } }
            public byte[] Bytes { get { return this.bytes; } } 
        }
    

    However, I would suggest you a much better method for prime number testing. For 64 bit numbers, no matter how large the number is, it gives the exact result in milliseconds.

    public static bool IsPrime(ulong number)
    {
        return number == 2 
            ? true 
            : (BigInterger.ModPow(2, number, number) == 2 
                ? (number & 1 != 0 && BinarySearchInA001567(number) == false) 
                : false)
    }
    
    public static bool BinarySearchInA001567(ulong number)
    {
        // Is number in list?
        // todo: Binary Search in A001567 (https://oeis.org/A001567) below 2 ^ 64
        // Only 2.35 Gigabytes as a text file http://www.cecm.sfu.ca/Pseudoprimes/index-2-to-64.html
    }
    

提交回复
热议问题