C ++ का उपयोग करके अभाज्य संख्या ज्ञात करने के लिए सबसे तेज़ एल्गोरिथम कौन सा है? मैंने छलनी के एल्गोरिथ्म का उपयोग किया है लेकिन मैं अभी भी इसे और तेज करना चाहता हूं!
C ++ का उपयोग करके अभाज्य संख्या ज्ञात करने के लिए सबसे तेज़ एल्गोरिथम कौन सा है? मैंने छलनी के एल्गोरिथ्म का उपयोग किया है लेकिन मैं अभी भी इसे और तेज करना चाहता हूं!
जवाबों:
Atkin की छलनी का एक बहुत तेजी से कार्यान्वयन डैन बर्नस्टीन का प्रमुख है । यह चलनी से अधिक कुशल है एरेटोस्थेनेज की चलनी । उनके पेज पर कुछ बेंचमार्क जानकारी है।
यदि इसे वास्तव में तेज़ होना है तो आप primes की सूची शामिल कर सकते हैं:
http://www.bigprimes.net/archive/prime/
यदि आपको बस यह जानना है कि एक निश्चित संख्या एक अभाज्य संख्या है, तो विकिपीडिया पर सूचीबद्ध विभिन्न प्राइम टेस्ट हैं । वे शायद यह निर्धारित करने के लिए सबसे तेज़ विधि हैं कि क्या बड़ी संख्याएँ primes हैं, खासकर क्योंकि वे आपको बता सकते हैं कि क्या संख्या एक प्रमुख नहीं है।
वह, मुझे पता है कि मैं पुराने प्रश्नों का उत्तर देने वाला एक प्रश्न परिचारक हूं, लेकिन मैंने यह प्रश्न कुशल अभाज्य संख्याओं को लागू करने के तरीकों के लिए नेट खोज कर पाया है।
अब तक, मेरा मानना है कि सबसे तेज़ प्राइम नंबर टेस्टिंग एल्गोरिदम स्ट्रॉन्ग प्रोबेबल प्राइम (SPRP) है। मैं एनवीडिया क्यूडा मंचों से उद्धृत कर रहा हूं:
संख्या सिद्धांत में अधिक व्यावहारिक आला समस्याओं में से एक को प्रमुख संख्याओं की पहचान करना है। N को देखते हुए, आप यह कैसे कुशलतापूर्वक निर्धारित कर सकते हैं कि यह प्रधान है या नहीं? यह सिर्फ एक थेरेटिकल समस्या नहीं है, यह कोड में एक वास्तविक आवश्यकता हो सकती है, शायद जब आपको कुछ सीमाओं के भीतर एक प्रमुख हैश तालिका आकार को गतिशील रूप से खोजने की आवश्यकता हो। यदि 2 ^ 30 के आदेश पर एन कुछ है, तो क्या आप वास्तव में किसी भी कारक की खोज के लिए 30000 डिवीजन परीक्षण करना चाहते हैं? बेशक नहीं।
इस समस्या का सामान्य व्यावहारिक समाधान एक सरल परीक्षण है जिसे यूलर प्रोबेबल प्राइम टेस्ट कहा जाता है, और एक अधिक शक्तिशाली सामान्यीकरण जिसे स्ट्रॉन्ग प्रोबेबल प्राइम (SPRP) कहा जाता है। यह एक परीक्षण है कि एक पूर्णांक के लिए N संभावित रूप से इसे प्रधान या नहीं के रूप में वर्गीकृत कर सकता है, और बार-बार परीक्षण सुधारात्मक संभावना को बढ़ा सकते हैं। परीक्षण के धीमे हिस्से में ज्यादातर A ^ (N-1) modulo N के समान मान शामिल होता है। RSA सार्वजनिक कुंजी एन्क्रिप्शन वेरिएंट को लागू करने वाले किसी भी व्यक्ति ने इस एल्गोरिथम का उपयोग किया है। यह विशाल पूर्णांक (जैसे 512 बिट्स) के साथ-साथ सामान्य 32 या 64 बिट इनट्स के लिए उपयोगी है।
परीक्षण को संभाव्य अस्वीकृति से एक निश्चित प्रमाण में प्रयोग किया जाता है जो कुछ परीक्षण इनपुट मापदंडों को पूर्वसंचालित करके प्रायोगिकता के एक निश्चित प्रमाण में बदल जाता है जो हमेशा एन की श्रेणियों के लिए सफल होते हैं। दुर्भाग्य से इन "सर्वश्रेष्ठ ज्ञात परीक्षणों" की खोज प्रभावी रूप से एक विशाल की खोज है। वास्तव में अनंत) डोमेन। 1980 में, कार्ल पोमेरेंस द्वारा प्रसिद्ध परीक्षणों की एक पहली सूची बनाई गई थी (जो उनके द्विघात सीव एल्गोरिथ्म के साथ एक कारक RSA-129 के लिए प्रसिद्ध है।) बाद में जैशेके ने 1993 में परिणामों में काफी सुधार किया। 2004 में, जांग और तांग ने सिद्धांत में सुधार किया। और खोज डोमेन की सीमा। Greathouse और Livingstone ने वेब पर अब तक के सबसे आधुनिक परिणामों को http://math.crg4.com/primes.html पर जारी किया है , जो एक विशाल खोज डोमेन का सबसे अच्छा परिणाम है।
अधिक जानकारी के लिए यहां देखें: http://primes.utm.edu/prove/prove2_3.html और http://forums.nvidia.com/index.php?showtopic=70483
यदि आपको बहुत बड़ी अभाज्य संख्याएँ उत्पन्न करने की आवश्यकता है और सभी अभाज्य संख्याएँ उत्पन्न करने की परवाह नहीं है <पूर्णांक n, तो आप Mersenne अभाज्य संख्याओं को सत्यापित करने के लिए Lucas-Lehmer परीक्षण का उपयोग कर सकते हैं। एक मेर्सन प्राइम नंबर 2 ^ पी -1 के रूप में है। मुझे लगता है कि लुकास-लेहमर परीक्षण सबसे तेज एल्गोरिथ्म है जो मेरसेन प्राइम नंबर के लिए खोजा गया है।
और अगर आप न केवल सबसे तेज़ एल्गोरिदम बल्कि सबसे तेज़ हार्डवेयर का भी उपयोग करना चाहते हैं, तो Nvidia CUDA का उपयोग करके इसे लागू करने का प्रयास करें, CUDA के लिए एक कर्नेल लिखें और इसे GPU पर चलाएं।
यदि आप बड़े प्राइम नंबर की खोज करते हैं तो आप कुछ पैसे भी कमा सकते हैं, EFF $ 50K से $ 250K तक पुरस्कार दे रहा है: https://www.eff.org/awards/coop
एक 100% गणितीय परीक्षण है जो यह जाँच करेगा कि कोई संख्या P
अभाज्य या मिश्रित है, जिसे AKS Primality Test कहा जाता है ।
अवधारणा सरल है: एक संख्या दी गई है P
, यदि सभी गुणांक (x-1)^P - (x^P-1)
विभाज्य हैं P
, तो P
एक अभाज्य संख्या है, अन्यथा यह एक संयुक्त संख्या है।
उदाहरण के लिए, दिया गया P = 3
, बहुपद देगा:
(x-1)^3 - (x^3 - 1)
= x^3 + 3x^2 - 3x - 1 - (x^3 - 1)
= 3x^2 - 3x
और गुणांक दोनों द्वारा विभाज्य हैं 3
, इसलिए संख्या प्रमुख है।
और उदाहरण के लिए P = 4
, जहां एक प्रमुख उपज नहीं है:
(x-1)^4 - (x^4-1)
= x^4 - 4x^3 + 6x^2 - 4x + 1 - (x^4 - 1)
= -4x^3 + 6x^2 - 4x
और यहाँ हम देख सकते हैं कि गुणांक 6
विभाज्य नहीं है 4
, इसलिए यह अभाज्य नहीं है।
बहुपद शर्तों का उपयोग (x-1)^P
करेगा P+1
और संयोजन का उपयोग करके पाया जा सकता है। तो, यह परीक्षण O(n)
रनटाइम में चलेगा , इसलिए मुझे नहीं पता कि यह कितना उपयोगी होगा क्योंकि आप केवल i
0 से अधिक तक पुनरावृत्ति कर सकते हैं p
और शेष के लिए परीक्षण कर सकते हैं ।
x
के लिए खड़ा है? में है (x-1)^P - (x^P-1)
। क्या आपके पास इसके लिए एक नमूना कोड है? C ++ में यह निर्धारित करने के लिए कि पूर्णांक प्रमुख है या नहीं?
क्या आपकी समस्या यह तय करने के लिए है कि क्या एक विशेष संख्या प्रमुख है? तब आपको एक परिक्षण परीक्षा (आसान) की आवश्यकता होती है। या क्या आपको किसी दिए गए नंबर तक सभी primes की आवश्यकता है? उस मामले में प्रमुख sieves अच्छे हैं (आसान है, लेकिन स्मृति की आवश्यकता है)। या क्या आपको किसी संख्या के प्रमुख कारकों की आवश्यकता है? इसके लिए फैक्टराइजेशन की आवश्यकता होगी (बड़ी संख्या के लिए मुश्किल अगर आप वास्तव में सबसे कुशल तरीके चाहते हैं)। आप कितनी बड़ी संख्या में देख रहे हैं? 16 बिट्स? 32 बिट्स? बड़ा?
एक चतुर और कुशल तरीका यह है कि आप पहले से ही प्राइम्स की तालिकाओं की गणना करें और उन्हें एक बिट-लेवल एन्कोडिंग का उपयोग करके फाइल में रखें। फ़ाइल को एक लंबा बिट वेक्टर माना जाता है जबकि बिट एन पूर्णांक एन का प्रतिनिधित्व करता है। यदि n अभाज्य है, तो इसका बिट एक और शून्य पर सेट है। लुकअप बहुत तेज़ है (आप बाइट ऑफ़सेट और बिट मास्क की गणना करते हैं) और फ़ाइल को मेमोरी में लोड करने की आवश्यकता नहीं है।
राबिन-मिलर एक मानक संभाव्य प्राणिकता परीक्षण है। (आप इसे K बार चलाते हैं और इनपुट नंबर या तो निश्चित रूप से समग्र है, या यह संभवतः त्रुटि 4 -K की संभावना के साथ प्रमुख है । (कुछ सौ पुनरावृत्तियों और यह लगभग निश्चित रूप से आपको सच्चाई बता रहा है)
राबिन मिलर का एक गैर-संभाव्य (निर्धारक) संस्करण है ।
द ग्रेट इंटरनेट मर्सन प्राइम सर्च (GIMPS) जिसने जून 2017 तक सबसे बड़ा सिद्ध प्रधान (2 74,207,281 - 1 ) के लिए दुनिया का रिकॉर्ड पाया है , कई एल्गोरिदम का उपयोग करता है , लेकिन ये विशेष रूपों में प्राइम हैं। हालाँकि ऊपर दिए गए GIMPS पृष्ठ में कुछ सामान्य नियतात्मक परिक्षण परीक्षण शामिल हैं। वे यह इंगित करने के लिए दिखाई देते हैं कि कौन सा एल्गोरिथ्म "सबसे तेज़" है, परीक्षण किए जाने वाले संख्या के आकार पर निर्भर करता है। यदि आपकी संख्या 64 बिट्स में फिट होती है, तो संभवत: आपको कई मिलियन अंकों के अपराधों पर काम करने के लिए एक विधि का उपयोग नहीं करना चाहिए।
यह आपके आवेदन पर निर्भर करता है। कुछ विचार हैं:
मिलर-राबिन और एनालॉग परीक्षण केवल एक निश्चित आकार से अधिक संख्या में छलनी से तेज होते हैं (कुछ मिलियन के आसपास, मुझे विश्वास है)। उसके नीचे, एक ट्रायल डिवीजन (यदि आपके पास बस कुछ नंबर हैं) या एक छलनी का उपयोग करना तेज है।
मैं हमेशा छलनी एल्गोरिथ्म के साथ प्राइम नंबर की गणना के लिए इस विधि का उपयोग करता हूं।
void primelist()
{
for(int i = 4; i < pr; i += 2) mark[ i ] = false;
for(int i = 3; i < pr; i += 2) mark[ i ] = true; mark[ 2 ] = true;
for(int i = 3, sq = sqrt( pr ); i < sq; i += 2)
if(mark[ i ])
for(int j = i << 1; j < pr; j += i) mark[ j ] = false;
prime[ 0 ] = 2; ind = 1;
for(int i = 3; i < pr; i += 2)
if(mark[ i ]) ind++; printf("%d\n", ind);
}
मैं आपको तय करने दूंगा कि यह सबसे तेज है या नहीं।
using System;
namespace PrimeNumbers
{
public static class Program
{
static int primesCount = 0;
public static void Main()
{
DateTime startingTime = DateTime.Now;
RangePrime(1,1000000);
DateTime endingTime = DateTime.Now;
TimeSpan span = endingTime - startingTime;
Console.WriteLine("span = {0}", span.TotalSeconds);
}
public static void RangePrime(int start, int end)
{
for (int i = start; i != end+1; i++)
{
bool isPrime = IsPrime(i);
if(isPrime)
{
primesCount++;
Console.WriteLine("number = {0}", i);
}
}
Console.WriteLine("primes count = {0}",primesCount);
}
public static bool IsPrime(int ToCheck)
{
if (ToCheck == 2) return true;
if (ToCheck < 2) return false;
if (IsOdd(ToCheck))
{
for (int i = 3; i <= (ToCheck / 3); i += 2)
{
if (ToCheck % i == 0) return false;
}
return true;
}
else return false; // even numbers(excluding 2) are composite
}
public static bool IsOdd(int ToCheck)
{
return ((ToCheck % 2 != 0) ? true : false);
}
}
}
यह लेता है लगभग 82 सेकंड खोजने के लिए और एक 2.40 GHz प्रोसेसर के साथ 1,000,000 1 की एक सीमा के भीतर रूढ़ अंक प्रिंट, मेरे कोर 2 डुओ लैपटॉप पर करने के लिए। और इसमें 78,498 प्राइम नंबर पाए गए ।
i <= (ToCheck / 3)
। यह होना चाहिए i <= (ToCheck / i)
। इसके साथ, यह बजाय 0.1 सेकंड में चल सकता है।
#include<stdio.h>
main()
{
long long unsigned x,y,b,z,e,r,c;
scanf("%llu",&x);
if(x<2)return 0;
scanf("%llu",&y);
if(y<x)return 0;
if(x==2)printf("|2");
if(x%2==0)x+=1;
if(y%2==0)y-=1;
for(b=x;b<=y;b+=2)
{
z=b;e=0;
for(c=2;c*c<=z;c++)
{
if(z%c==0)e++;
if(e>0)z=3;
}
if(e==0)
{
printf("|%llu",z);
r+=1;
}
}
printf("|\n%llu outputs...\n",r);
scanf("%llu",&r);
}
मैं किसी पूर्वनिर्धारित एल्गोरिथ्म के बारे में नहीं जानता, लेकिन मैंने अपना स्वयं का बनाया जो बहुत तेज़ है। यह 1 सेकंड से भी कम समय में 20 अंकों की संख्या को संसाधित कर सकता है। इस कार्यक्रम की अधिकतम क्षमता 18446744073709551615 है। यह कार्यक्रम है:
#include <iostream>
#include <cmath>
#include <stdlib.h>
using namespace std;
unsigned long long int num = 0;
bool prime() {
if (num % 2 == 0 || num == 1) {
return false;
}
unsigned long int square_root = sqrt(num);
for (unsigned long int i = 3; i <= square_root; i += 2) {
if (num % i == 0) {
return false;
}
}
return true;
}
int main() {
do {
system("cls");
cout << "Enter number : ";
cin >> num;
if (prime()) {
cout << "The number is a prime number" << endl << endl << endl << endl;
} else {
cout << "The number is not a prime number" << endl << endl << endl << endl;
}
system("pause");
} while (1);
return 0;
}
#include <iostream>
using namespace std;
int set [1000000];
int main (){
for (int i=0; i<1000000; i++){
set [i] = 0;
}
int set_size= 1000;
set [set_size];
set [0] = 2;
set [1] = 3;
int Ps = 0;
int last = 2;
cout << 2 << " " << 3 << " ";
for (int n=1; n<10000; n++){
int t = 0;
Ps = (n%2)+1+(3*n);
for (int i=0; i==i; i++){
if (set [i] == 0) break;
if (Ps%set[i]==0){
t=1;
break;
}
}
if (t==0){
cout << Ps << " ";
set [last] = Ps;
last++;
}
}
//cout << last << endl;
cout << endl;
system ("pause");
return 0;
}
(n%2)+1+(3*n)
हालांकि अच्छा की तरह है। :)
मुझे पता है कि यह कुछ समय बाद है, लेकिन यह खोज से यहां पहुंचने वाले लोगों के लिए उपयोगी हो सकता है। वैसे भी, यहां कुछ जावास्क्रिप्ट इस तथ्य पर निर्भर करती है कि केवल प्रमुख कारकों का परीक्षण करने की आवश्यकता है, इसलिए कोड द्वारा उत्पन्न पहले के primes का उपयोग बाद के लोगों के लिए परीक्षण कारकों के रूप में फिर से किया जाता है। बेशक, सभी समान और आधुनिक 5 मान पहले फ़िल्टर किए गए हैं। परिणाम सरणी P में होगा, और यह कोड एक i7 पीसी (या लगभग 20 में 100 मिलियन) पर 1.5 सेकंड से कम में 10 मिलियन prunch को क्रंच कर सकता है। सी में फिर से लिखा यह बहुत तेज होना चाहिए।
var P = [1, 2], j, k, l = 3
for (k = 3 ; k < 10000000 ; k += 2)
{
loop: if (++l < 5)
{
for (j = 2 ; P[j] <= Math.sqrt(k) ; ++j)
if (k % P[j] == 0) break loop
P[P.length] = k
}
else l = 0
}
#include<iostream>
using namespace std;
void main()
{
int num,i,j,prime;
cout<<"Enter the upper limit :";
cin>>num;
cout<<"Prime numbers till "<<num<<" are :2, ";
for(i=3;i<=num;i++)
{
prime=1;
for(j=2;j<i;j++)
{
if(i%j==0)
{
prime=0;
break;
}
}
if(prime==1)
cout<<i<<", ";
}
}
break;
भी धीमा होगा, हे (एन ^ 2), लेकिन इसे पहले से ही कोडिंग त्रुटि के रूप में देखा जा सकता है। primes द्वारा बचत और परीक्षण O (N ^ 2 / (log N) ^ 2) है, और केवल संख्या वर्गमूल से नीचे के primes द्वारा परीक्षण O (N ^ 1.5 / (log N) ^ 2) है।