I've written the following C++ code to factorize really large numbers efficiently (numbers up to 24997300729).
I have a vector containing 41000 primes approx.( I know having such a large vector isn't a good idea although but couldn't figure a way around this).
This code produces the prime factorization of moderately large numbers in no time but when it comes to numbers such as, 24997300572 the program stalls.
Here's the program below with some screenshots of the output:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cmath>
using namespace std;
vector<int> primes = {paste from
https://drive.google.com/file/d/1nGvtMMQSa9YIDkMW2jgEbJk67P7p54ft/view?usp=sharing
};
void factorize(int n) {
if (n == 1)
return;
if (find(primes.begin(), primes.end(), n) != primes.end()) {
cout << n <<" "; //if n is prime dont'proceed further
return;
}
//obtaining an iterator to the location of prime equal to or just greater than sqrt(n)
auto s = sqrt(n);
vector<int>::iterator it = lower_bound(primes.begin(), primes.end(), s);
if (it == primes.end()) {
return; // if no primes found then the factors are beyond range
}
for (auto i = it;i != primes.begin();i--) {
if (n % *i == 0)
{
cout << *i << " ";
n = n / (*i);
factorize(n);
return; // the two consecutive for() loops should never run one after another
}
}
for (auto i = it;i != primes.end();i++) {
if (n % *i == 0)
{
cout << *i << " ";
n = n / (*i);
factorize(n);
return; // the two consecutive for() loops should never run one after another
}
}
}
int main() {
unsigned int n;
cout << "Enter a number between 1 and 24997300729 ";
cin >> n;
if (n > 24997300729) {
cout << "Number out of range;";
exit(-1);
}
factorize(n);
return 0;
}
This is OK
But This is NOT!!!
I tried using long long int and long double wherever I could to over come the problem of large numbers, but that didn't help much.
Any help Would Be Greatly Appreciated
It's a little unclear (at least to me) exactly why you've structured the program the way you have.
You can fully factor a number by only looking for prime factors less than or equal to that number's square root. Any prime factor larger than those pairs with one prime factors smaller than that, so you only have to search for those to find all the prime factors. Any remaining factors can be obtained by simple division, not searching.
I'd probably generate the base of prime numbers on the fly (mostly likely using a sieve). The square root of 24'997'300'729 is (about) 158'105. A quick test shows that even without any work on optimization, a sieve of Eratosthenes will find the primes up to that limit in about 12 milliseconds.
Personally, I'd rather not have a fixed limit on the largest number the user can factor, other than the limit on the size of number we're working with, so if the user enters something close to the limit for a 64-bit number, we find all the primes that fit in 32 bits, and then use those to factor the number. This will obviously be slower than if we don't find as many primes, but a user probably won't be too surprised at the idea that factoring a larger number takes longer than factoring a smaller number.
So, implementing that, we might end up with code something like this:
#include <iostream>
#include <locale>
#include <vector>
#include <string>
using Number = unsigned long long;
auto build_base(Number limit) {
std::vector<bool> sieve(limit / 2, true);
for (Number i = 3; i < limit; i += 2) {
if (sieve[i / 2]) {
for (Number temp = i * i; temp < limit; temp += i)
if (temp & 1)
sieve[temp / 2] = false;
}
}
return sieve;
}
void factor(Number input, std::vector<bool> const &candidates)
{
while (input % 2 == 0) {
std::cout << 2 << "\t";
input /= 2;
}
for (Number i = 1; i < candidates.size(); i++) {
if (candidates[i]) {
auto candidate = i * 2 + 1;
while ((input % candidate) == 0) {
std::cout << candidate << "\t";
input /= candidate;
}
}
}
if (input != 1)
std::cout << input;
}
int main(int argc, char **argv) {
std::cout.imbue(std::locale(""));
if (argc != 2) {
std::cerr << "Usage: factor <number>\n";
return EXIT_FAILURE;
}
auto number = std::stoull(argv[1]);
auto limit = std::sqrt(number) + 1;
auto candidates = build_base(limit);
factor(number, candidates);
}
At a high level, the code works like this: we start by finding the primes up to the square root of the number the user entered. Since we want all the primes up to a limit, we use a sieve of Eratosthenes to find them. This builds a vector of bools, in which vector[n] will be true if n is prime, and false if n is composite. It does this starting from 3 (2 is a special case we kind of ignore for now) and crossing off the multiples of three. Then it finds the next number that hasn't been crossed off (which will be five, in this case), and crosses off its multiples. It continues doing that until it reaches the end of the array. To save some space, it leaves all the even numbers out of the array, because (other than that special case for 2) we already know none of them is prime.
Once we have that, we use those prime numbers to find prime factors of the number we want to factor. This proceeds pretty simply: walk through the vector of primes, and test whether each prime number divides evenly into the target number. If it does, print it out, divide it out of the target number, and continue.
At least for me, this seems to work pretty dependably, and is reasonably fast. If we wanted to do a better job of factoring larger numbers, the next big step would be to switch to a segmented sieve. This can improve the speed of the first part of the job by a pretty wide margin, allowing us (for example) to factor anything that'll fit into a 64-bit number in no more than about 10 seconds.
Related
I made this program for generating prime numbers. I know there are lots of formulas for generating them 100x faster, but this is what I did.
I tried to divide i with all numbers under i. That was the simplest method, but I though it was inefficient, since after dividing by 2 you don't need to divide by 4 and so on.
I made a list of prime numbers smaller than i, and divided i by that list's numbers. I went through the list using std::iterator, because I saw it being used in all stackoverflow answers and other tutorials. It turned out to be a lot slower. Like it took 22 seconds instead of 2.
I tried to use an int to go through the list, and it took 2 seconds again.
Next, I used 1 000 000 to see the difference between method 1 and 3. To my amazement method 1 was faster. Why is that? Shouldn't using only prime numbers to test be faster than using all numbers?
#include <iostream>
#include <vector>
#include <chrono>
int main()
{
std::cout << "how high do you want to generate prime numbers? ";
int x;
// typed 1 000 000
std::cin >> x;
auto starttime = std::chrono::high_resolution_clock::now();
std::vector<unsigned int> primes;
bool isPrime;
for (int i = 2; i <= x; ++i) {
isPrime = true;
// takes 293 seconds
//for (int div{ 2 }; div < i; ++div) {
// if ((i % div) == 0) {
// takes really really long
//for (std::vector<unsigned int>::iterator div = primes.begin(); div != primes.end(); ++div) {
//if ((i % *div) == 0) {
// takes 356 seconds
for (int iter = 0; iter < primes.size(); ++iter) {
if ((i % primes[iter]) == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
primes.push_back(i);
std::cout << i << " ";
}
}
std::cout << "generating prime numbers up to " << x << " took " <<
round(static_cast<std::chrono::duration<double>>((std::chrono::high_resolution_clock::now() - starttime)).count())
<< " seconds.";
}
its because of usage vector<unsinged int> for third method.
especially primes.push_back which leads to allocations. Try to primes.reserve initially
I'd say the main issue is that most frequently a number is divisible by 2 and thus it isn't prime. I suppose the first method is more friendly with compiler and cache. But it is hard to tell for sure. Also, try to remove printing and test for time spent. Printing tends to slow the code a lot depending on usage.
A standart method for determining all prime numbers (there are more efficient ones but this one is fairly simple).
Create vector A of boolean that will indicate whether the number is prime or not. But at start set all variables to true - except A[0]=A[1]=false.
Run for loop from i = 2 to x. If A[i] is false then skip it - i is not prime. If A[i] is true then i is prime and set all A[i*k] to false for all 1<k<x/i.
This should be more efficient either of the methods.
to find factors of number, i am using function void primeFactors(int n)
# include <stdio.h>
# include <math.h>
# include <iostream>
# include <map>
using namespace std;
// A function to print all prime factors of a given number n
map<int,int> m;
void primeFactors(int n)
{
// Print the number of 2s that divide n
while (n%2 == 0)
{
printf("%d ", 2);
m[2] += 1;
n = n/2;
}
// n must be odd at this point. So we can skip one element (Note i = i +2)
for (int i = 3; i <= sqrt(n); i = i+2)
{
// While i divides n, print i and divide n
while (n%i == 0)
{
int k = i;
printf("%d ", i);
m[k] += 1;
n = n/i;
}
}
// This condition is to handle the case whien n is a prime number
// greater than 2
if (n > 2)
m[n] += 1;
printf ("%d ", n);
cout << endl;
}
/* Driver program to test above function */
int main()
{
int n = 72;
primeFactors(n);
map<int,int>::iterator it;
int to = 1;
for(it = m.begin(); it != m.end(); ++it){
cout << it->first << " appeared " << it->second << " times "<< endl;
to *= (it->second+1);
}
cout << to << " total facts" << endl;
return 0;
}
You can check it here. Test case n = 72.
http://ideone.com/kaabO0
How do I solve above problem using above algo. (Can it be optimized more ?). I have to consider large numbers as well.
What I want to do ..
Take example for N = 864, we found X = 72 as (72 * 12 (no. of factors)) = 864)
There is a prime-factorizing algorithm for big numbers, but actually it is not often used in programming contests.
I explain 3 methods and you can implementate using this algorithm.
If you implementated, I suggest to solve this problem.
Note: In this answer, I use integer Q for the number of queries.
O(Q * sqrt(N)) solution per query
Your algorithm's time complexity is O(n^0.5).
But you are implementating with int (32-bit), so you can use long long integers.
Here's my implementation: http://ideone.com/gkGkkP
O(sqrt(maxn) * log(log(maxn)) + Q * sqrt(maxn) / log(maxn)) algorithm
You can reduce the number of loops because composite numbers are not neccesary for integer i.
So, you can only use prime numbers in the loop.
Algorithm:
Calculate all prime numbers <= sqrt(n) with Eratosthenes's sieve. The time complexity is O(sqrt(maxn) * log(log(maxn))).
In a query, loop for i (i <= sqrt(n) and i is a prime number). The valid integer i is about sqrt(n) / log(n) with prime number theorem, so the time complexity is O(sqrt(n) / log(n)) per query.
More efficient algorithm
There are more efficient algorithm in the world, but it is not used often in programming contests.
If you check "Integer factorization algorithm" on the internet or wikipedia, you can find the algorithm like Pollard's-rho or General number field sieve.
Well,I will show you the code.
# include <stdio.h>
# include <iostream>
# include <map>
using namespace std;
const long MAX_NUM = 2000000;
long prime[MAX_NUM] = {0}, primeCount = 0;
bool isNotPrime[MAX_NUM] = {1, 1}; // yes. can be improve, but it is useless when sieveOfEratosthenes is end
void sieveOfEratosthenes() {
//#see https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
for (long i = 2; i < MAX_NUM; i++) { // it must be i++
if (!isNotPrime[i]) //if it is prime,put it into prime[]
prime[primeCount++] = i;
for (long j = 0; j < primeCount && i * prime[j] < MAX_NUM; j++) { /*foreach prime[]*/
// if(i * prime[j] >= MAX_NUM){ // if large than MAX_NUM break
// break;
// }
isNotPrime[i * prime[j]] = 1; // set i * prime[j] not a prime.as you see, i * prime[j]
if (!(i % prime[j])) //if this prime the min factor of i,than break.
// and it is the answer why not i+=( (i & 1) ? 2 : 1).
// hint : when we judge 2,prime[]={2},we set 2*2=4 not prime
// when we judge 3,prime[]={2,3},we set 3*2=6 3*3=9 not prime
// when we judge 4,prime[]={2,3},we set 4*2=8 not prime (why not set 4*3=12?)
// when we judge 5,prime[]={2,3,5},we set 5*2=10 5*3=15 5*5=25 not prime
// when we judge 6,prime[]={2,3,5},we set 6*2=12 not prime,than we can stop
// why not put 6*3=18 6*5=30 not prime? 18=9*2 30=15*2.
// this code can make each num be set only once,I hope it can help you to understand
// this is difficult to understand but very useful.
break;
}
}
}
void primeFactors(long n)
{
map<int,int> m;
map<int,int>::iterator it;
for (int i = 0; prime[i] <= n; i++) // we test all prime small than n , like 2 3 5 7... it musut be i++
{
while (n%prime[i] == 0)
{
cout<<prime[i]<<" ";
m[prime[i]] += 1;
n = n/prime[i];
}
}
cout<<endl;
int to = 1;
for(it = m.begin(); it != m.end(); ++it){
cout << it->first << " appeared " << it->second << " times "<< endl;
to *= (it->second+1);
}
cout << to << " total facts" << endl;
}
int main()
{
//first init for calculate all prime numbers,for example we define MAX_NUM = 2000000
// the result of prime[] should be stored, you primeFactors will use it
sieveOfEratosthenes();
//second loop for i (i*i <= n and i is a prime number). n<=MAX_NUM
int n = 72;
primeFactors(n);
n = 864;
primeFactors(n);
return 0;
}
My best shot at performance without getting overboard with special algos.
The Erathostenes' seive - the complexity of the below is O(N*log(log(N))) - because the inner j loop starts from i*i instead of i.
#include <vector>
using std::vector;
void erathostenes_sieve(size_t upToN, vector<size_t>& primes) {
primes.clear();
vector<bool> bitset(upToN+1, true); // if the bitset[i] is true, the i is prime
bitset[0]=bitset[1]=0;
// if i is 2, will jump to 3, otherwise will jump on odd numbers only
for(size_t i=2; i<=upToN; i+=( (i&1) ? 2 : 1)) {
if(bitset[i]) { // i is prime
primes.push_back(i);
// it is enough to start the next cycle from i*i, because all the
// other primality tests below it are already performed:
// e.g:
// - i*(i-1) was surely marked non-prime when we considered multiples of 2
// - i*(i-2) was tested at (i-2) if (i-2) was prime or earlier (if non-prime)
for(size_t j=i*i; j<upToN; j+=i) {
bitset[j]=false; // all multiples of the prime with value of i
// are marked non-prime, using **addition only**
}
}
}
}
Now factoring based on the primes (set in a sorted vector). Before this, let's examine the myth of sqrt being expensive but a large bunch of multiplications is not.
First of all, let us note that sqrt is not that expensive anymore: on older CPU-es (x86/32b) it used to be twice as expensive as a division (and a modulo operation is division), on newer architectures the CPU costs are equal. Since factorisation is all about % operations again and again, one may still consider sqrt now and then (e.g. if and when using it saves CPU time).
For example consider the following code for an N=65537 (which is the 6553-th prime) assuming the primes has 10000 entries
size_t limit=std::sqrt(N);
size_t largestPrimeGoodForN=std::distance(
primes.begin(),
std::upper_limit(primes.begin(), primes.end(), limit) // binary search
);
// go descendingly from limit!!!
for(int i=largestPrimeGoodForN; i>=0; i--) {
// factorisation loop
}
We have:
1 sqrt (equal 1 modulo),
1 search in 10000 entries - at max 14 steps, each involving 1 comparison, 1 right-shift division-by-2 and 1 increment/decrement - so let's say a cost equal with 14-20 multiplications (if ever)
1 difference because of std::distance.
So, maximal cost - 1 div and 20 muls? I'm generous.
On the other side:
for(int i=0; primes[i]*primes[i]<N; i++) {
// factorisation code
}
Looks much simpler, but as N=65537 is prime, we'll go through all the cycle up to i=64 (where we'll find the first prime which cause the cycle to break) - a total of 65 multiplications.
Try this with a a higher prime number and I guarantee you the cost of 1 sqrt+1binary search are better use of the CPU cycle than all the multiplications on the way in the simpler form of the cycle touted as a better performance solution
So, back to factorisation code:
#include <algorithm>
#include <math>
#include <unordered_map>
void factor(size_t N, std::unordered_map<size_t, size_t>& factorsWithMultiplicity) {
factorsWithMultiplicity.clear();
while( !(N & 1) ) { // while N is even, cheaper test than a '% 2'
factorsWithMultiplicity[2]++;
N = N >> 1; // div by 2 of an unsigned number, cheaper than the actual /2
}
// now that we know N is even, we start using the primes from the sieve
size_t limit=std::sqrt(N); // sqrt is no longer *that* expensive,
vector<size_t> primes;
// fill the primes up to the limit. Let's be generous, add 1 to it
erathostenes_sieve(limit+1, primes);
// we know that the largest prime worth checking is
// the last element of the primes.
for(
size_t largestPrimeIndexGoodForN=primes.size()-1;
largestPrimeIndexGoodForN<primes.size(); // size_t is unsigned, so after zero will underflow
// we'll handle the cycle index inside
) {
bool wasFactor=false;
size_t factorToTest=primes[largestPrimeIndexGoodForN];
while( !( N % factorToTest) ) {
wasFactor=true;// found one
factorsWithMultiplicity[factorToTest]++;
N /= factorToTest;
}
if(1==N) { // done
break;
}
if(wasFactor) { // time to resynchronize the index
limit=std::sqrt(N);
largestPrimeIndexGoodForN=std::distance(
primes.begin(),
std::upper_bound(primes.begin(), primes.end(), limit)
);
}
else { // no luck this time
largestPrimeIndexGoodForN--;
}
} // done the factoring cycle
if(N>1) { // N was prime to begin with
factorsWithMultiplicity[N]++;
}
}
here x,y<=10^12 and y-x<=10^6
i have looped from left to right and checked each number for a prime..this method is very slow when x and y are somewhat like 10^11 and 10^12..any faster approach?
i hv stored all primes till 10^6..can i use them to find primes between huge values like 10^10-10^12?
for(i=x;i<=y;i++)
{
num=i;
if(check(num))
{
res++;
}
}
my check function
int check(long long int num)
{
long long int i;
if(num<=1)
return 0;
if(num==2)
return 1;
if(num%2==0)
return 0;
long long int sRoot = sqrt(num*1.0);
for(i=3; i<=sRoot; i+=2)
{
if(num%i==0)
return 0;
}
return 1;
}
Use a segmented sieve of Eratosthenes.
That is, use a bit set to store the numbers between x and y, represented by x as an offset and a bit set for [0,y-x). Then sieve (eliminate multiples) for all the primes less or equal to the square root of y. Those numbers that remain in the set are prime.
With y at most 1012 you have to sieve with primes up to at most 106, which will take less than a second in a proper implementation.
This resource goes through a number of prime search algorithms in increasing complexity/efficiency. Here's the description of the best, that is PG7.8 (you'll have to translate back to C++, it shouldn't be too hard)
This algorithm efficiently selects potential primes by eliminating multiples of previously identified primes from consideration and
minimizes the number of tests which must be performed to verify the
primacy of each potential prime. While the efficiency of selecting
potential primes allows the program to sift through a greater range of
numbers per second the longer the program is run, the number of tests
which need to be performed on each potential prime does continue to
rise, (but rises at a slower rate compared to other algorithms).
Together, these processes bring greater efficiency to generating prime
numbers, making the generation of even 10 digit verified primes
possible within a reasonable amount of time on a PC.
Further skip sets can be developed to eliminate the selection of potential primes which can be factored by each prime that has already
been identified. Although this process is more complex, it can be
generalized and made somewhat elegant. At the same time, we can
continue to eliminate from the set of test primes each of the primes
which the skip sets eliminate multiples of, minimizing the number of
tests which must be performed on each potential prime.
You can use the Sieve of Eratosthenes algorithm. This page has some links to implementations in various languages: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes.
Here is my implementation of Sieve of Erathostenes:
#include <string>
#include <iostream>
using namespace std;
const int k = 110000; //you can change this constant to whatever maximum int you would need to calculate
long int p[k]; //here we would store Sieve of Erathostenes from 2 to k
long int j;
void init_prime() //in here we set our array
{
for (int i = 2; i <= k; i++)
{
if (p[i] == 0)
{
j = i;
while (j <= k)
{
p[j] = i;
j = j + i;
}
}
}
/*for (int i = 2; i <= k; i++)
cout << p[i] << endl;*/ //if you uncomment this you can see the output of initialization...
}
string prime(int first, int last) //this is example of how you can use initialized array
{
string result = "";
for (int i = first; i <= last; i++)
{
if (p[i] == i)
result = result + to_str(i) + "";
}
return result;
}
int main() //I done this code some time ago for one contest, when first input was number of cases and then actual input came in so nocases means "number of cases"...
{
int nocases, first, last;
init_prime();
cin >> nocases;
for (int i = 1; i <= nocases; i++)
{
cin >> first >> last;
cout << prime(first, last);
}
return 0;
}
You can use the Sieve of Erathostenes to calculate factorial too. This is actually the fastest interpretation of the Sieve I could manage to create that day (it can calculate the Sieve of this range in less than a second)
What is the most optimized approach of finding out the number of divisors of a number,such that the divisors have at least the digit 3 in it?
e.g. 21=1,3,7,21
therefore only one divisor has the digit 3 in it.
e.g.
62=1,2,31,62
therefore only one divisor has the digit 3 in it and i.e. 31
EDIT-i realized that the best way to do this woulds be to find out all the factors of a number and check for the factors containing the digit 3.
the best way to find out the factors :
Getting Factors of a Number
What is the best way to get all the divisors of a number?
Here is an expansion on my take. It first checks if there is a possible factor in the list div3. If not, it adds candidates up to number/2, skipping values that already could be factored according to this list, so '37' and '43' get added, but not '36' or '39'.
The above part should be considered "setup". If you know the input constraints (a maximum input value), you can calculate the vector div3 once, then store it inside the program.
If the list div3 is up to date, the input should be factored into one of these numbers. If it can't then none of its factors contain a '3'. If it can, this shows the remainder, which can be factored further using conventional methods.
I consider this "optimized" because the constraint "any factor should contain a '3'" is checked first. Only if any valid factor is found, you need to calculate all the others.
My first program using <vector> and its ilk, so be gentle in your comments :-)
(Edit) I now notice the factor checking loop goes over the entire div3 vector. Of course, it only needs to go up to number/2. Left as an exercise to the reader.
(Additional edit) find3 is here a reverse iterator. For some reason that seemed appropriate, but I can't recall why I thought so :) If checking up to and including number/2, you need to change it to a regular forward iterator.
#include <iostream>
#include <vector>
using namespace std;
int contains_3 (int value)
{
while (value && (value % 10) != 3)
value /= 10;
return value;
}
int main (int argc, char **argv)
{
int number, found_flag, last_div3, adjust, adjust_digit;
vector<int> div3;
vector<int>::reverse_iterator find3;
vector<int>::iterator it;
// a little seeding
div3.push_back(3);
div3.push_back(13);
div3.push_back(23);
if (argc != 2)
return -1;
number = atoi (argv[1]);
found_flag = 0;
// do we need to expand div3?
last_div3 = div3.back();
while (last_div3 * 2 < number)
{
// if this number contains a '3' in any other place than the last,
// simply increment it
if ((last_div3 % 10) != 9 && contains_3(last_div3/10))
{
last_div3++;
} else
{
// no? then simply pick the next multiple of 10 and add 3
last_div3 /= 10;
last_div3++;
last_div3 *= 10;
if (!contains_3(last_div3))
last_div3 += 3;
}
// check if it should be in the list
for (it = div3.begin() ; it != div3.end() && (last_div3 % *it); ++it) ;
if (it == div3.end())
{
div3.push_back(last_div3);
}
}
cout << "list is now: ";
for (it = div3.begin() ; it != div3.end(); ++it)
cout << ' ' << *it;
cout << endl;
for (find3 = div3.rbegin(); !found_flag && find3 != div3.rend(); find3++)
{
if (!(number % *find3))
{
cout << "candidate: " << *find3 << ", remaining to sieve: " << number/(*find3) << endl;
found_flag++;
}
}
if (!found_flag)
cout << "None found" << endl;
return 0;
}
I'm trying to find the largest prime factor of the number 600851475143. My code works for smaller numbers that I test (below 100). However when confronted with 600851475143, it returns 4370432, definitely not prime. Any ideas what could be wrong with my code?
#include <iostream>
#include <time.h>
#include <math.h>
using namespace std;
int main()
{
int num;
int largest;
int count;
cout<<"Please enter a number to have its Largest Prime Factor found"<<endl;
cin>>num;
num = 600851475143;
for (int factor = 1; factor <= num; factor++)
{
if (num % factor == 0)
{
count = 0;
for (int primetest=2; count == 0 && factor > primetest ; primetest++)
{
if (factor % primetest == 0)
count ++;
//endif
}
if (count == 0)
largest = factor;
//endif
}
}//endif
cout<<largest<<endl;
system("PAUSE");
}
num = 600851475143;
Integer overflow occurs here. The size of num is not large enough to contain the value which you've provided.
Use uint64_t.
#include <cstdint> //must include this!
uint64_t num = 600851475143;
Read this : cstdint
There are quite a few major problems with the code, so I want to show a better complete
solution. The main problem is that it has no input validation! Good code must be correct
on all inputs it does not reject. So I have now included proper reading and validation of
input. In this way you would have automatically caught the problem.
All major types need to have proper names! So I have introduce the typedef uint_type.
The compiler will also find out already at compile-time, if the input 60085147514 is
valid or not (though this now is also rejected at run-time). If the compiler warns,
then you need to use a bigger integer-type; however unsigned long is enough on all common
64-bit platforms (but not on common 32-bit platforms). If you need bigger integer types,
then now just one place has to be changed.
Your algorithm is horribly inefficient! All what is needed is to divide the number through
all factors found (as long as possible), and you are guaranteed to only encounter prime
numbers -- so no need to check for that. And also one only needs to consider factors up to
the square-root of the input. This all requires a bit of logic to think through -- see
the code.
Then your code violates the principle of locality: declare your variables where they are
needed, not somewhere else. You also included non-C++ headers, which furthermore were
not needed. The use of using-directives just obfuscates the code: you don't see anymore
where the components come from; and there is no need for them! I also introduced an
anonymous namespace, for the more prominent definitions.
Finally, I use a more compact coding-style (indentation by 2 spaces, brackets on the
same line, avoiding brackets if possible. Think about it: in this way you can see much
more at one glance, while with a bit of training it is also easier to read.
When compiled as shown, the compiler warns about largest_factor possibly used undefined.
This is not the case, and I opted here to consider that warning as empty.
Program LargestPrimeFactor.cpp:
// Compile with
// g++ -O3 -Wall -std=c++98 -pedantic -o LargestPrimeFactor LargestPrimeFactor.cpp
#include <string>
#include <iostream>
namespace {
const std::string program_name = "LargestPrimeFactor";
const std::string error_output = "ERROR[" + program_name + "]: ";
const std::string version_number = "0.1";
enum ErrorCodes { reading_error = 1, range_error = 2 };
typedef unsigned long uint_type;
const uint_type example = 600851475143; // compile-time warnings will show
// whether uint_type is sufficient
}
int main() {
uint_type number;
std::cout << "Please enter a number to have its largest prime factor found:"
<< std::endl;
std::cin >> number;
if (not std::cin) {
std::cerr << error_output << "Number not of the required unsigned integer"
" type.\n";
return reading_error;
}
if (number <= 1) {
std::cerr << error_output << "Number " << number << " has no largest prime"
" factor.\n";
return range_error;
}
const uint_type input = number;
uint_type largest_factor;
for (uint_type factor = 2; factor <= number/factor; ++factor)
if (number % factor == 0) {
largest_factor = factor;
do number /= factor; while (number % factor == 0);
}
if (number != 1) largest_factor = number;
std::cout << "The largest prime factor of " << input << " is " << largest_factor
<< ".\n";
}
And to offer a correction. Depending on your compiler you could try unsigned long and see if that could hold your answer. Try and write to cout and see if the variable holds the value you expect.
On another note, if you are trying to find the largest factor would it not be more efficient to count down from the highest possible factor?
You can declare your num variable as long long int.
long long int num;
This will avoid all the types of overflows occurring in your code!
C++ Program to find the largest prime factor of number.
#include <iostream>
#include<bits/stdc++.h>
using namespace std;
// A function to find largest prime factor
long long maxPrimeFactors(long long n)
{
// Initialize the maximum prime factor
// variable with the lowest one
long long maxPrime = -1;
// Print the number of 2s that divide n
while (n % 2 == 0) {
maxPrime = 2;
n >>= 1; // equivalent to n /= 2
}
// n must be odd at this point
while (n % 3 == 0) {
maxPrime = 3;
n=n/3;
}
// now we have to iterate only for integers
// who does not have prime factor 2 and 3
for (int i = 5; i <= sqrt(n); i += 6) {
while (n % i == 0) {
maxPrime = i;
n = n / i;
}
while (n % (i+2) == 0) {
maxPrime = i+2;
n = n / (i+2);
}
}
// This condition is to handle the case
// when n is a prime number greater than 4
if (n > 4)
maxPrime = n;
return maxPrime;
}
// Driver program to test above function
int main()
{
long long n = 15;
cout << maxPrimeFactors(n) << endl;
n = 25698751364526;
cout << maxPrimeFactors(n);
}