Sau khi đọc câu hỏi này, tôi bị thu hút bởi thực tế là một số câu trả lời cung cấp tối ưu hóa bằng cách chạy một vòng lặp với bội số của 2 * 3 = 6.
Vì vậy, tôi tạo một hàm mới với ý tưởng tương tự, nhưng với bội số của 2 * 3 * 5 = 30.
int check235(unsigned long n)
{
unsigned long sq, i;
if(n<=3||n==5)
return n>1;
if(n%2==0 || n%3==0 || n%5==0)
return 0;
if(n<=30)
return checkprime(n);
sq=ceil(sqrt(n));
for(i=7; i<=sq; i+=30)
if (n%i==0 || n%(i+4)==0 || n%(i+6)==0 || n%(i+10)==0 || n%(i+12)==0
|| n%(i+16)==0 || n%(i+22)==0 || n%(i+24)==0)
return 0;
return 1;
}
Bằng cách chạy cả hai chức năng và kiểm tra thời gian, tôi có thể nói rằng chức năng này thực sự nhanh hơn. Cho phép xem 2 bài kiểm tra với 2 số nguyên tố khác nhau:
$ time ./testprimebool.x 18446744069414584321 0
f(2,3)
Yes, its prime.
real 0m14.090s
user 0m14.096s
sys 0m0.000s
$ time ./testprimebool.x 18446744069414584321 1
f(2,3,5)
Yes, its prime.
real 0m9.961s
user 0m9.964s
sys 0m0.000s
$ time ./testprimebool.x 18446744065119617029 0
f(2,3)
Yes, its prime.
real 0m13.990s
user 0m13.996s
sys 0m0.004s
$ time ./testprimebool.x 18446744065119617029 1
f(2,3,5)
Yes, its prime.
real 0m10.077s
user 0m10.068s
sys 0m0.004s
Vì vậy, tôi nghĩ, liệu ai đó có đạt được quá nhiều nếu khái quát không? Tôi đã nghĩ ra một hàm sẽ thực hiện một cuộc bao vây trước tiên để làm sạch một danh sách các số nguyên tố ban đầu đã cho, và sau đó sử dụng danh sách này để tính toán số nguyên tố lớn hơn.
int checkn(unsigned long n, unsigned long *p, unsigned long t)
{
unsigned long sq, i, j, qt=1, rt=0;
unsigned long *q, *r;
if(n<2)
return 0;
for(i=0; i<t; i++)
{
if(n%p[i]==0)
return 0;
qt*=p[i];
}
qt--;
if(n<=qt)
return checkprime(n);
if((q=calloc(qt, sizeof(unsigned long)))==NULL)
{
perror("q=calloc()");
exit(1);
}
for(i=0; i<t; i++)
for(j=p[i]-2; j<qt; j+=p[i])
q[j]=1;
for(j=0; j<qt; j++)
if(q[j])
rt++;
rt=qt-rt;
if((r=malloc(sizeof(unsigned long)*rt))==NULL)
{
perror("r=malloc()");
exit(1);
}
i=0;
for(j=0; j<qt; j++)
if(!q[j])
r[i++]=j+1;
free(q);
sq=ceil(sqrt(n));
for(i=1; i<=sq; i+=qt+1)
{
if(i!=1 && n%i==0)
return 0;
for(j=0; j<rt; j++)
if(n%(i+r[j])==0)
return 0;
}
return 1;
}
Tôi cho rằng tôi đã không tối ưu hóa mã, nhưng điều đó là công bằng. Bây giờ, các bài kiểm tra. Vì có rất nhiều bộ nhớ động, tôi dự kiến danh sách 2 3 5 sẽ chậm hơn một chút so với 2 3 5 được mã hóa cứng. Nhưng nó vẫn ổn như bạn có thể thấy dưới đây. Sau đó, thời gian ngày càng nhỏ lại, dẫn đến danh sách tốt nhất là:
2 3 5 7 11 13 17 19
Với 8,6 giây. Vì vậy, nếu ai đó muốn tạo một chương trình mã hóa cứng sử dụng kỹ thuật như vậy, tôi khuyên bạn nên sử dụng danh sách 2 3 và 5, bởi vì lợi ích không lớn như vậy. Nhưng ngoài ra, nếu sẵn sàng viết mã, danh sách này là ok. Vấn đề là bạn không thể nêu tất cả các trường hợp mà không có vòng lặp, hoặc mã của bạn sẽ rất lớn (Sẽ có 1658879 ORs
, đó là ||
trong nội bộ tương ứng if
). Danh sách tiếp theo:
2 3 5 7 11 13 17 19 23
thời gian bắt đầu lớn hơn, với 13 giây. Đây là toàn bộ bài kiểm tra:
$ time ./testprimebool.x 18446744065119617029 2 3 5
f(2,3,5)
Yes, its prime.
real 0m12.668s
user 0m12.680s
sys 0m0.000s
$ time ./testprimebool.x 18446744065119617029 2 3 5 7
f(2,3,5,7)
Yes, its prime.
real 0m10.889s
user 0m10.900s
sys 0m0.000s
$ time ./testprimebool.x 18446744065119617029 2 3 5 7 11
f(2,3,5,7,11)
Yes, its prime.
real 0m10.021s
user 0m10.028s
sys 0m0.000s
$ time ./testprimebool.x 18446744065119617029 2 3 5 7 11 13
f(2,3,5,7,11,13)
Yes, its prime.
real 0m9.351s
user 0m9.356s
sys 0m0.004s
$ time ./testprimebool.x 18446744065119617029 2 3 5 7 11 13 17
f(2,3,5,7,11,13,17)
Yes, its prime.
real 0m8.802s
user 0m8.800s
sys 0m0.008s
$ time ./testprimebool.x 18446744065119617029 2 3 5 7 11 13 17 19
f(2,3,5,7,11,13,17,19)
Yes, its prime.
real 0m8.614s
user 0m8.564s
sys 0m0.052s
$ time ./testprimebool.x 18446744065119617029 2 3 5 7 11 13 17 19 23
f(2,3,5,7,11,13,17,19,23)
Yes, its prime.
real 0m13.013s
user 0m12.520s
sys 0m0.504s
$ time ./testprimebool.x 18446744065119617029 2 3 5 7 11 13 17 19 23 29
f(2,3,5,7,11,13,17,19,23,29)
q=calloc(): Cannot allocate memory
Tái bút. Tôi đã không cố ý giải phóng (r), giao nhiệm vụ này cho Hệ điều hành, vì bộ nhớ sẽ được giải phóng ngay sau khi chương trình thoát ra, để có thêm thời gian. Nhưng sẽ là khôn ngoan nếu bạn giải phóng nó nếu bạn định tiếp tục chạy mã của mình sau khi tính toán.
TẶNG KEM
int check2357(unsigned long n)
{
unsigned long sq, i;
if(n<=3||n==5||n==7)
return n>1;
if(n%2==0 || n%3==0 || n%5==0 || n%7==0)
return 0;
if(n<=210)
return checkprime(n); /* use another simplified function */
sq=ceil(sqrt(n));
for(i=11; i<=sq; i+=210)
{
if(n%i==0 || n%(i+2)==0 || n%(i+6)==0 || n%(i+8)==0 || n%(i+12)==0 ||
n%(i+18)==0 || n%(i+20)==0 || n%(i+26)==0 || n%(i+30)==0 || n%(i+32)==0 ||
n%(i+36)==0 || n%(i+42)==0 || n%(i+48)==0 || n%(i+50)==0 || n%(i+56)==0 ||
n%(i+60)==0 || n%(i+62)==0 || n%(i+68)==0 || n%(i+72)==0 || n%(i+78)==0 ||
n%(i+86)==0 || n%(i+90)==0 || n%(i+92)==0 || n%(i+96)==0 || n%(i+98)==0 ||
n%(i+102)==0 || n%(i+110)==0 || n%(i+116)==0 || n%(i+120)==0 || n%(i+126)==0 ||
n%(i+128)==0 || n%(i+132)==0 || n%(i+138)==0 || n%(i+140)==0 || n%(i+146)==0 ||
n%(i+152)==0 || n%(i+156)==0 || n%(i+158)==0 || n%(i+162)==0 || n%(i+168)==0 ||
n%(i+170)==0 || n%(i+176)==0 || n%(i+180)==0 || n%(i+182)==0 || n%(i+186)==0 ||
n%(i+188)==0 || n%(i+198)==0)
return 0;
}
return 1;
}
Thời gian:
$ time ./testprimebool.x 18446744065119617029 7
h(2,3,5,7)
Yes, its prime.
real 0m9.123s
user 0m9.132s
sys 0m0.000s