Tutaj zabawkowy program do testowania całych przedziałów. W pythonie można się wzorować na tym kodzie. Sprawdzenie przedziału od 2 do miliona trwa niecałą minutę. Czy działą poprawnie dla wszystkich liczb - nie wiem. Można tam dodać test pierwszość millera-rabina - powinno przyspieszyć oblicznenia:
Kompilacja i uruchomienie:
c++ -std=c++11 -O3 main.cpp -o perfectNumber
./perfectNumber
Podaj minimum przedziału: 2
Podaj maksimum przedziału: 1000000
6 is perfect! 1, 2, 3 primes[9, 23]
28 is perfect! 1, 2, 4, 7, 14 primes[9, 23]
496 is perfect! 1, 2, 4, 8, 16, 31, 62, 124, 248 primes[1009, 8011]
8128 is perfect! 1, 2, 4, 8, 16, 32, 64, 127, 254, 508, 1016, 2032, 4064 primes[1009, 8011]
benchmark: 58.0424
Podaj minimum przedziału: ^C
m@SSDB:~/Dokumenty/c/eduPerfectNumber$ c++ -std=c++11 -O3 main.cpp -o perfectNumber
m@SSDB:~/Dokumenty/c/eduPerfectNumber$ ./perfectNumber
Podaj minimum przedziału: 2
Podaj maksimum przedziału: 1000000
6 is perfect! 1, 2, 3 primes[9, 23]
28 is perfect! 1, 2, 4, 7, 14 primes[9, 23]
496 is perfect! 1, 2, 4, 8, 16, 31, 62, 124, 248 primes[1009, 8011]
8128 is perfect! 1, 2, 4, 8, 16, 32, 64, 127, 254, 508, 1016, 2032, 4064 primes[2009, 17471]
benchmark: 96.1287
Podaj minimum przedziału: ^C
m@SSDB:~/Dokumenty/c/eduPerfectNumber$ c++ -std=c++11 -O3 main.cpp -o perfectNumber
m@SSDB:~/Dokumenty/c/eduPerfectNumber$ ./perfectNumber
Podaj minimum przedziału: 2
Podaj maksimum przedziału: 10000
6 is perfect! 1, 2, 3 primes[9, 23]
28 is perfect! 1, 2, 4, 7, 14 primes[9, 23]
496 is perfect! 1, 2, 4, 8, 16, 31, 62, 124, 248 primes[1009, 8011]
8128 is perfect! 1, 2, 4, 8, 16, 32, 64, 127, 254, 508, 1016, 2032, 4064 primes[1009, 8011]
benchmark: 0.0299189
Podaj minimum przedziału: 2
Podaj maksimum przedziału: 100000
6 is perfect! 1, 2, 3 primes[1009, 8011]
28 is perfect! 1, 2, 4, 7, 14 primes[1009, 8011]
496 is perfect! 1, 2, 4, 8, 16, 31, 62, 124, 248 primes[1009, 8011]
8128 is perfect! 1, 2, 4, 8, 16, 32, 64, 127, 254, 508, 1016, 2032, 4064 primes[1009, 8011]
benchmark: 0.961177
Podaj minimum przedziału: 2
Podaj maksimum przedziału: 1000000
6 is perfect! 1, 2, 3 primes[6009, 59441]
28 is perfect! 1, 2, 4, 7, 14 primes[6009, 59441]
496 is perfect! 1, 2, 4, 8, 16, 31, 62, 124, 248 primes[6009, 59441]
8128 is perfect! 1, 2, 4, 8, 16, 32, 64, 127, 254, 508, 1016, 2032, 4064 primes[6009, 59441]
benchmark: 58.4139
Kod źródłowy
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
#include <chrono>
#include <cmath>
using utyp = unsigned int;
using ultyp = unsigned long long;
using cultyp = const ultyp;
static std::vector<ultyp> primes = {2,3,5,7,11,13,17,19,23};
static void addPrimes() {
utyp found=0;
ultyp next = primes[ primes.size() - 1 ] + 2;
while( found < 1000 ) {
size_t i=0;
while( i<primes.size() && next % primes[i] ) {
i++;
}
if( i == primes.size() ) {
primes.push_back( next );
found++;
}
next += 2;
}
}
static void insert( std::vector<ultyp> &r , cultyp prime , cultyp v ) {
const size_t size = r.size();
for( size_t i=0 ; i<size ; i++ ) {
if( v > prime * r[i] ) {
if( std::find( r.begin() , r.end() , prime * r[i] ) == r.end() ) {
r.push_back( prime * r[i] );
}
}
}
}
static bool millerRabinTest(cultyp v) {
//not implemented yet
//example: https://github.com/cslarsen/miller-rabin/blob/master/miller-rabin.cpp
return false;
}
static void divides( ultyp v , std::vector<ultyp> &d ) {
cultyp cpyV = v;
d.resize(1);
d[0] = 1;
ultyp i=0;
while( primes[i] <= v && primes[i] <= cpyV/2 ) {
if( v % primes[i] == 0 ) {
v /= primes[i];
insert( d , primes[i] , cpyV );
} else if( millerRabinTest( v ) ) {
insert( d , v , cpyV );
break;
} else if( ++i >= primes.size() ) {
addPrimes();
}
}
}
static bool isPerfect( cultyp v ) {
static std::vector<ultyp> d;
divides( v , d );
ultyp sum = 0;
for( size_t i=0 ; sum <= v && i < d.size() ; i++ ) {
sum += d[i];
}
return v == sum;
}
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
while( true ) {
ultyp min,max;
std::cout << "Podaj minimum przedziału: ";
std::cin >> min;
std::cout << "Podaj maksimum przedziału: ";
std::cin >> max;
const auto start = std::chrono::system_clock::now();
for( ultyp i=min ; i<=max ; i++) {
if( isPerfect( i ) ) {
std::cout << i << " is perfect! ";
std::vector<ultyp> d;
divides( i , d );
std::sort( d.begin() , d.end() );
for( size_t i=0 ; i<d.size() ; i++ ) {
if( i > 0 ) {
std::cout << ", ";
}
std::cout << d[i];
}
std::cout << " primes[" << primes.size() << ", " << primes[primes.size()-1] << "]";
std::cout<< std::endl;
}
}
{
const auto end = std::chrono::system_clock::now();
const std::chrono::duration<double> elapsed = end - start;
std::cout << "benchmark: " << elapsed.count() << std::endl;
}
std::cout << std::endl << std::endl;
}
return 0;
}