素数判断详解
参考文章:点击打开链接
对于判断素数大概有两类方法1:试除法2:筛选法
还有一个米勒-拉宾检验方法此处不再展开。
试除法:不断地尝试能否整除。比如要判断自然数 x 是否质数,就不断尝试小于 x 且大于1的自然数,只要有一个能整除,则 x 是合数;否则,x 是质数。
筛选法:首先,2是公认最小的质数,所以,先把所有2的倍数去掉;然后剩下的那些大于2的数里面,最小的是3,所以3也是质数;然后把所有3的倍数都去掉,剩下的那些大于3的数里面,最小的是5,所以5也是质数……上述过程不断重复,就可以把某个范围内的合数全都除去(就像被筛子筛掉一样),剩下的就是质数了。
筛选法如图所示
具体代码如下:
/** 判断素数最优的方法 */
bool isPrimeOptimize(int n){
int i = 2;
//这里的(n / i)是从筛选法中获取的比例值
// i/j 米勒/拉宾检验
for (; i <= (n / i); i++) {
if (n % i == 0) {
break;
}
}
if (i > (n / i)) {
//NSLog(@"此数是素数 %d", n);
return true;
}
return false;
}
/** 判断素数开根号方法 */
bool isPrimeSqrt(int n){
int i = 2;
int sqrtN = sqrt(n);
for (; i <= sqrt(n); i++) {
if (n % i == 0) {
break;
}
}
if (i > sqrtN) {
//NSLog(@"此数是素数 %d", n);
return true;
}
return false;
}
#define kDefault (-1)
#define kDefaultNot (0)
#define kDefaultYes (1)
bool isTestSelecting(int n){
#if 0 - 测试
for (int i = 2; i <= 100; i++) {
bool is = isPrime(i);
if (is) {
printf("this is prime %d\n", i);
}
}
return false;
#endif
#if 1 - 筛选法每位按int数据来处理
int length = n + 1;//从0开始
int arr[length];
memset(arr, kDefault, sizeof(int) * length);
for (int i = 0; i <= n; i++) {
printf("the arr[%d] is %d\n", i, arr[i]);
}
arr[1] = kDefaultYes;
for (int i = 2; i <= n; i++) {
bool isPrimeBool = false;
if (arr[i] == kDefaultNot) {
isPrimeBool = false;
}else{
isPrimeBool = isPrimeOptimize(i);
arr[i] = kDefaultYes;
}
if (isPrimeBool) {
for (int j = i; j <= n / i; j++) {
//i*j = n;
int position = i * j;
arr[position] = kDefaultNot;//kDefaultValue is No
}
}
}
for (int i = 1; i <= n; i++) {
//printf("the arr[%d] is %d\n", i, arr[i]);
if (arr[i] == kDefaultYes) {
printf("the value is %d\n", i);
}
}
return false;
#endif
}
void print_int_8bit(char value){
unsigned char index = 0x80;
while(index > 0){
putchar(value & index ? '1' : '0');
index >>= 1;
}
printf("\n");
}
void setPositionBit(char *pointer, int position, int v){
char value = pointer[position / 8];
print_int_8bit(value);
if (v == 0) {
value = (~(0x01 << (position % 8))) & value;
pointer[position / 8] = value;
print_int_8bit(value);
}else if (v == 1){
value = (0x01 << (position % 8)) | value;
pointer[position / 8] = value;
print_int_8bit(value);
}
}
bool getbitValue(char *pointer, int position){
return pointer[position / 8] >> (position % 8) & 0x01;
}
/** 判断素数筛选法每位按照位来处理 */
void testIsPrimeSelecting(int n){
int length = n + 1;//从0开始
int align8 = align8Bit(length);
char * pointer = (char *)calloc(align8, sizeof(char));
//默认都是
memset(pointer, 0xff, sizeof(char) * align8);
//从0开始第一位设为1
for (int i = 0; i <= n; i++) {
printf("the pointer[%d] is %d\n", i, pointer[i / 8] >> (i % 8) & 0x01);
}
for (int i = 0; i <= n; i++) {
printf("the pointer[%d] is %d\n", i, pointer[i / 8] >> (i % 8) & 0x01);
}
for (int i = 2; i <= n; i++) {
bool isPrimeBool = false;
if (getbitValue(pointer, i) == false) {
isPrimeBool = false;
}else{
isPrimeBool = isPrimeOptimize(i);
if (isPrimeBool == false) {
setPositionBit(pointer, i, kDefaultNot);
}
}
if (isPrimeBool) {
for (int j = i; j <= n / i; j++) {
int position = i * j;
setPositionBit(pointer, position, kDefaultNot);
}
}
}
for (int i = 1; i <= n; i++) {
if (getbitValue(pointer, i) == true) {
printf("the value 是素数 is %d\n", i);
}
}
}
unsigned int align8Bit(unsigned int n){
return calc_alignFounction2(n, 8);
}
unsigned int calc_alignFounction1(unsigned int n,unsigned align){
if (n / align * align == n) {
return n;
}
return (n / align + 1) * align;
}
/*
例如8字节对齐要求,后三位为0.
(align-1)表示后三位111.
size+(aling-1)会导致进位。
&~(aling-1)去除后面多余的。
*/
unsigned int calc_alignFounction2(unsigned int n, unsigned align){
return (n + (align - 1)) & (~(align - 1));
}