An even number can always be expressed as the sum of two prime numbers. C language algorithm

Posted by Noumes on Tue, 23 Nov 2021 11:30:00 +0100

I happened to see a program similar to Goldbach's conjecture on CSDN:

C language daily practice - day 52: an even number can always be expressed as the sum of two prime numbers_ Super Hui sir blog CSDN blog C language daily practice November 3, 2021 - Analysis: Although I can't prove this conjecture in C language, I can set a range and prove that the number in the range meets this condition. Idea: three-layer loop: the first layer traverses all even numbers greater than 2 (given range), the second layer traverses the first prime addend, and the third layer traverses the second prime addend. Only when all even numbers have two prime addends (addends of prime numbers) can it be proved that within this number range, an even number can always be expressed as the sum of two prime numbers.https://blog.csdn.net/weixin_43772810/article/details/121129617 I felt it was a little interesting, so I tried to write it myself. Because I hadn't written C language for a long time, I spared a little detour, but I also wrote it, so I sent it out to make a fool of myself. Ignore the code style and write it casually. Tested some data and felt that the performance was OK.

4-1 million even numbers, 41 seconds;

990000 to 1 million, 10000 data, less than 1 second.

Send the result first, and the code is attached.

jie@Jies-MacBook-Pro test1 % ./a.out  
your input: 4 - 1000000
 Program run time: 41373.597 ms
jie@Jies-MacBook-Pro test1 % ./a.out  
your input: 990000 - 1000000
 Program run time: 927.436 ms

The algorithm has two ideas:

1. Sharpen the knife without mistaking the firewood cutter

        In any case, the calculation of prime numbers should not be repeated. Just run enough at one time and put them there for standby. From the actual situation, the calculation of prime numbers below millions is still very fast;

2. Addition algorithm

        The two head approximation algorithm is adopted, min=2, max = the prime number closest to the input number, the larger one and the smaller one do not matter. Take 168 as an example.

The first round: min=2, max=167, the sum is greater than 168, maxIndex-1

Second round: min=2, max=163, sum less than 168, minIndex+1

The third round: min=3, max=163, the sum is less than 168, minIndex+1

The fourth round: min=5, max=163, sum = 168, successful.  

In addition, there is room for optimization in theory, because so many calculations are independent and there is no interaction between various numbers. In theory, multi-core computing can be used. If necessary, it can be selected according to the actual scene.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

typedef int BOOL;
#define TRUE 1
#define FALSE 0

#define MAX_PRIME_LENGTH 1000000
long _primes[MAX_PRIME_LENGTH];

void calcPrimes(long max);
int isPrime(long x);
long findSmallerPrimeIndex(long number);
int divideNumber(long number, long* x, long* y);

int main()
{
    double start = clock();

    long min = 990000;
    long max = 1000000;
    printf("your input: %ld - %ld\n", min, max);

    calcPrimes(max*2);
    
    for(long i=min; i<=max; i+=2){
        long x=0, y=0;
        divideNumber(i, &x, &y);
        //printf("%ld = %ld + % ld\n", i, _primes[x], _primes[y]);
    }

    double end = clock();
    printf("Program run time:%.3f ms\n",(double)(end-start)/1000); //Print run time

    return 0;
}


// Divide a number into the sum of two prime numbers
int divideNumber(long number, long* x, long* y){
    // Start at both ends, starting with the largest number less than number
    long maxPrimeIndex = findSmallerPrimeIndex(number);
    //printf("maxPrimeIndex = %ld\n", maxPrimeIndex);
    long indexX = 0;
    long indexY = maxPrimeIndex;

    // *x to right, * y to left
    while(indexX < indexY)
    {
        //printf("min = %ld, max = %ld\n", _primes[indexX], _primes[indexY]);
        long r = _primes[indexX] + _primes[indexY];
        if(r < number){
            indexX++;
        } else if(r > number){
            indexY--;
        }else{
            *x = indexX;
            *y = indexY;
            return 0;
        }
    }
    return -1;

}

// Find the prime number closest to number and less than number (there may be a bug in this place. The found number may not be less than, but may be greater than, but it has little impact on performance)
long findSmallerPrimeIndex(long number){
    long i=0;
    for(i=0; _primes[i]<=number; i++);

    return i;
}

// Calculates all prime numbers less than max
void calcPrimes(long max){
    long index = 0;
    for(long i=0; i<MAX_PRIME_LENGTH; i++){
        _primes[i] = 0;
    }
    for(long i=2; i<max; i++){
        if(isPrime(i) == TRUE){
            _primes[index++] = i;
        }
    }
}

// Judge whether it is prime
BOOL isPrime(long x){
    // As long as it can be_ Divide the contents in primes, even if it fails
    for(long i=0; _primes[i]<=sqrt(x); i++){
        long m = _primes[i];
        if(x % m == 0){
            return FALSE;
        }
    }
    return TRUE;
}

Topics: Algorithm