以下都是测试int 32bit范围内的质数。
例如:1-200000014范围内有11078937个质数。
大数要用专门的类,支持任意范围大数。
质数定理给出了一个近似估计小于等于 n 的质数个数的公式:
π(n) ≈ n / ln(n)
其中 π(n) 表示小于等于 n 的质数个数,ln(n) 表示 n 的自然对数。这个公式在 n 很大时比较准确,但 n 较小时误差较大。
例如:小于等于 0xFFFFFFFF 的质数有 n/ln(n)==193635251 个。
0xFFFFFFFF 以内有2亿左右个质数,数量非常多,密度也很大,
这也是质数分解可以作为密码的原因。
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <math.h>//质数判断
bool is_prime_optimized(int n) {if (n <= 1) {return false;}int i2 = (int)sqrt(n);for (int i = 2; i <= i2; i++) {if (n % i == 0) {return false;}}return true;
}
//有限大小的质数缓存
int eratosthenes_sieve(int limit, int *count, int ** prime_array) {if (NULL== count || NULL==prime_array) {return -1;}*count = 0;*prime_array = NULL;if (limit < 2) {return 0;}bool* is_prime = (bool*)malloc(sizeof(bool) * (limit + 1));if (NULL == is_prime) {goto ERROR;}for (int i = 0; i <= limit; i++) {is_prime[i] = true;}is_prime[0] = is_prime[1] = false;for (int p = 2; p * p <= limit; p++) {if (is_prime[p]) {for (int i = p * p; i <= limit; i += p) {//至少从p * p开始is_prime[i] = false;}}}int count_temp = 0;for (int p = 2; p <= limit; p++) {if (is_prime[p]) {++count_temp;}}*count = count_temp;*prime_array = (int*)malloc(sizeof(int) * count_temp);if (NULL==*prime_array) {goto ERROR;}count_temp = 0;for (int p = 2; p <= limit; p++) {if (is_prime[p]) {(*prime_array)[count_temp] = p;++count_temp;}}free(is_prime);return 0;ERROR:if (is_prime) {free(is_prime);is_prime = NULL;}if (*prime_array) {free(*prime_array);*prime_array = NULL;}*count = 0;return -1;
}
以下为简单测试代码
int main(int argc, char* argv[]){int i1 = 200000014;unsigned int i2 = 0xFFFFFFFF;int count = 0;int* prime_array = NULL;printf("小于等于 %d 的质数有 n/ln(n)==%.0f 个。\n", i1, (double)i1 / log(i1));//10463629printf("小于等于 0xFFFFFFFF 的质数有 n/ln(n)==%.0f 个。\n", (double)i2 / log(i2));//193635251eratosthenes_sieve(i1,&count,&prime_array);printf("小于等于 %d 的质数有 %d 个。\n", i1, count);//11078937//for (int i = 0; i < count; i++) {// printf("%d,", prime_array[i]);//}int a= 64577;printf("%d is prime %d\n",a , is_prime_optimized(a));for (int i = 0; i < count; i++) {while (0 == a % prime_array[i]) {printf("%d ", prime_array[i]);a = a / prime_array[i];}if (1 == a)break;}if (prime_array) {free(prime_array);}return 0;
}
win11下vs2022的CMakeLists.txt内容如下
cmake_minimum_required(VERSION 3.10)
project(ctest VERSION 0.1 LANGUAGES C)
set(CMAKE_C_STANDARD 99)add_executable(ctest main.c)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")target_compile_options(ctest PRIVATE -O0 -g -DDEBUG)
else()target_compile_options(ctest PRIVATE -O2 -g)
endif()