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);
}
Related
I'm trying to write a prime number indentify-er, but every time I try to divide the inputted number, it won't go to the decimals. I've tried using a double variable and float variable. I'm a beginner, so I might have to ask a few questions about your answer. Here is the code (looper is the number I used for the while function to keep it going).
#include <iostream>
int main() {
int input = 0;
float result = 0;
int looper = 2;
std::cout << "Please enter your number.\n";
std::cin >> input;
if (input == 1 or input == 0) {
std::cout << "Your number is neither.\n";
}
while (looper < 1000002) {
result = input / looper;
std::cout << input / looper;
if (fmod(result, 1) == 0) {
std::cout << "Your number is composite.\n";
std::cout << result;
looper = 1000003;
}
else if (fmod(result, 1) != 0) {
std::cout << "Your number is prime.\n";
}
looper = looper + 1;
}
}
There are some rules for arithmetic calculations.
if any of the operands is float or double, then the result is truncated to the float or double type respectively (int < float and int < double cause the size of int, float, double are 4, 8, 8 bytes respectively, but the sizes may be different depending on os & compiler.
if any of the operands is long type, then the result is truncated to the long type (int < long cause the size of int long types are 4, 8 bytes respectively, but the sizes may be different depending on os & compiler.)
However, you can do better alternative ( use moduler operator %) here like following:
if (input % looper == 0) {
// case for composit
// in other words input value is completely divisible by current value of looper
}
else {
// input value is not completely divisible by current value of looper
// this means there is a remainder exists
}
Though you have put the printf statement for prime number at wrong place, your provided algorithm is can be improved to determine whether an integer number is prime or not.
I would like to find the largest prime factor of a given number. After several attempts, I've enhanced the test to cope with rather big numbers (i.e. up to one billion in milliseconds). The problem is now if go beyond one billion, the execution time goes forever, so to speak. I wonder if I can do more improvements and reduce the execution time. I'm hoping for better execution time because in this link Prime Factors Calculator, the execution time is incredibly fast. My target number at this moment is 600851475143. The code is rather self-explanatory. Note: I've considered Sieve of Eratosthenes algorithm with no luck regarding the execution time.
#include <iostream>
#include <cmath>
bool isPrime(int n)
{
if (n==2)
return true;
if (n%2==0)
return false;
for (int i(3);i<=sqrt(n);i+=2) // ignore even numbers and go up to sqrt(n)
if (n%i==0)
return false;
return true;
}
int main()
{
int max(0);
long long target(600851475143);
if( target%2 == 0 )
max = 2;
for ( int i(3); i<target; i+=2 ){ // loop through odd numbers.
if( target%i == 0 ) // check for common factor
if( isPrime(i) ) // check for prime common factor
max = i;
}
std::cout << "The greatest prime common factor is " << max << "\n";
return 0;
}
One obvious optimization that I can see is:
for (int i(3);i<=sqrt(n);i+=2) // ignore even numbers and go up to sqrt(n)
instead of calculating sqrt everytime you can cache the result in a variable.
auto maxFactor = static_cast<int>sqrt(n);
for (int i(3); i <= maxFactor; i+=2);
The reason I believe this could lead to speed up is sqrt deals with floating point arithematic and compilers usually aren't generous in optimizing floating point arithematic. gcc has a special flag ffast-math to enable floating point optimizations explicitely.
For numbers upto the target range that you mentioned, you will need better algorithms. repeated divisioning should suffice.
Here is the code (http://ideone.com/RoAmHd) which hardly takes any time to finish:
int main() {
long long input = 600851475143;
long long mx = 0;
for (int x = 2; x <= input/x; ++x){
while(input%x==0) {input/=x; mx = x; }
}
if (input > 1){
mx = input;
}
cout << mx << endl;
return 0;
}
The idea behind repeated division is if a number is already a factor of p, it is also a factor of p^2, p^3, p^4..... So we keep eliminating factors so only prime factors remain that eventually get to divide the number.
You don't need a primality test. Try this algorithm:
function factors(n)
f := 2
while f * f <= n
if n % f == 0
output f
n := n / f
else
f := f + 1
output n
You don't need a primality test because the trial factors increase by 1 at each step, so any composite trial factors will have already been handled by their smaller constituent primes.
I'll leave it to you to implement in C++ with appropriate data types. This isn't the fastest way to factor integers, but it is sufficient for Project Euler 3.
for ( int i(3); i<target; i+=2 ){ // loop through odd numbers.
if( target%i == 0 ) // check for common factor
if( isPrime(i) ) // check for prime common factor
max = i;
It is the first two lines of this code, not primality checks, which take almost all time. You divide target to all numbers from 3 to target-1. This takes about target/2 divisions.
Besides, target is long long, while i is only int. It is possible that the size is too small, and you get an infinite loop.
Finally, this code does not calculate the greatest prime common factor. It calculate the greatest prime divisor of target, and does it very inefficiently. So what do you really need?
And it is a bad idea to call anything "max" in c++, because max is a standard function.
Here is my basic version:
int main() {
long long input = 600851475143L;
long long pMax = 0;
// Deal with prime 2.
while (input % 2 == 0) {
input /= 2;
pMax = 2;
}
// Deal with odd primes.
for (long long x = 3; x * x <= input; x += 2) {
while (input % x == 0) {
input /= x;
pMax = x;
}
}
// Check for unfactorised input - must be prime.
if (input > 1) {
pMax = input;
}
std::cout << "The greatest prime common factor is " << pMax << "\n";
return 0;
}
It might be possible to speed things up further by using a Newton-Raphson integer square root method to set up a (mostly) fixed limit for the loop. If available that would need a rewrite of the main loop.
long long limit = iSqrt(input)
for (long long x = 3; x <= limit; x += 2) {
if (input % x == 0) {
pMax = x;
do {
input /= x;
} while (input % x == 0);
limit = iSqrt(input); // Value of input changed so reset limit.
}
}
The square root is only calculated when a new factor is found and the value of input has changed.
Note that except for 2 and 3, all prime numbers are adjacent to multiples of 6.
The following code reduces the total number of iterations by:
Leveraging the fact mentioned above
Decreasing target every time a new prime factor is found
#include <iostream>
bool CheckFactor(long long& target,long long factor)
{
if (target%factor == 0)
{
do target /= factor;
while (target%factor == 0);
return true;
}
return false;
}
long long GetMaxFactor(long long target)
{
long long maxFactor = 1;
if (CheckFactor(target,2))
maxFactor = 2;
if (CheckFactor(target,3))
maxFactor = 3;
// Check only factors that are adjacent to multiples of 6
for (long long factor = 5, add = 2; factor*factor <= target; factor += add, add = 6-add)
{
if (CheckFactor(target,factor))
maxFactor = factor;
}
if (target > 1)
return target;
return maxFactor;
}
int main()
{
long long target = 600851475143;
std::cout << "The greatest prime factor of " << target << " is " << GetMaxFactor(target) << std::endl;
return 0;
}
I tried a code on a coding website to find the largest prime factor of a number and it's exceeding the time limit for the last test case where probably they are using a large prime number. Can you please help me to reduce the complexity of the following code?
int main()
{
long n;
long int lar, fact;
long int sqroot;
int flag;
cin >> n;
lar=2, fact=2;
sqroot = sqrt(n);
flag = 0;
while(n>1)
{
if((fact > sqroot) && (flag == 0)) //Checking only upto Square Root
{
cout << n << endl;
break;
}
if(n%fact == 0)
{
flag = 1;
lar = fact;
while(n%fact == 0)
n = n/fact;
}
fact++;
}
if(flag == 1) //Don't display if loop fact reached squareroot value
cout << lar << endl;
}
Here I've also taken care of the loop checking till Square Root value. Still, how can I reduce its complexity further?
You can speed things up (if not reduce the complexity) by supplying a hard-coded list of the first N primes to use for the initial values of fact, since using composite values of fact are a waste of time. After that, avoid the obviously composite values of fact (like even numbers).
You can reduce the number of tests by skipping even numbers larger than 2, and stopping sooner if you have found smaller factors. Here is a simpler and faster version:
int main() {
unsigned long long n, lar, fact, sqroot;
cin >> n;
lar = 0;
while (n && n % 2 == 0) {
lar = 2;
n /= 2;
}
fact = 3;
sqroot = sqrt(n);
while (fact <= sqroot) {
if (n % fact == 0) {
lar = fact;
do { n /= fact; } while (n % fact == 0);
sqroot = sqrt(n);
}
fact += 2;
}
if (lar < n)
lar = n;
cout << lar << endl;
return 0;
}
I am not sure how large the input numbers may become, using the larger type unsigned long long for these computations will get you farther than long. Using a precomputed array of primes would help further, but not by a large factor.
The better result I've obtained is using the function below (lpf5()). It's based on the primality() function (below) that uses the formulas 6k+1, 6k-1 to individuate prime numbers. All prime numbers >= 5 may be expressed in one of the forms p=k*6+1 or p=k*6-1 with k>0 (but not all the numbers having such a forms are primes). Developing these formulas we can see a sequence like the following:
k=1 5,7
k=2 11,13
k=3 17,19
k=4 23,25*
k=5 29,31
.
.
.
k=10 59,61
k=11 65*,67
k=12 71,73
...
5,7,11,13,17,19,23,25,29,31,...,59,61,65,67,71,73,...
We observe that the difference between the terms is alternatively 2 and 4. Such a results may be obtained also using simple math. Is obvious that the difference between k*6+1 and k*6-1 is 2. It's simple to note that the difference between k*6+1 and (k+1)*6-1 is 4.
The function primality(x) returns x when x is prime (or 0 - take care) and the first divisor occurs when x is not prime.
I think you may obtain a better result inlining the primality() function inside the lpf5() function.
I've also tried to insert a table with some primes (from 1 to 383 - the primes in the first 128 results of the indicated formulas) inside the primality function, but the speed difference is unappreciable.
Here the code:
#include <stdio.h>
#include <math.h>
typedef long long unsigned int uint64;
uint64 lpf5(uint64 x);
uint64 primality(uint64 x);
uint64 lpf5(uint64 x)
{
uint64 x_=x;
while ( (x_=primality(x))!=x)
x=x/x_;
return x;
}
uint64 primality(uint64 x)
{
uint64 div=7,f=2,q;
if (x<4 || x==5)
return x;
if (!(x&1))
return 2;
if (!(x%3))
return 3;
if (!(x%5))
return 5;
q=sqrt(x);
while(div<=q) {
if (!(x%div)) {
return div;
}
f=6-f;
div+=f;
}
return x;
}
int main(void) {
uint64 x,k;
do {
printf("Input long int: ");
if (scanf("%llu",&x)<1)
break;
printf("Largest Prime Factor: %llu\n",lpf5(x));
} while(x!=0);
return 0;
}
This question already has answers here:
Finding largest prime number out of 600851475143?
(3 answers)
Closed 9 years ago.
Can't find the prime factor of 600851475143 for projecteuler. My code successfully computes the largest prime factor of the test number 13195 and every test number I throw at it, but somehow it degrades with the large prime number. Do you know why?
#include <iostream>
#include <queue>
using namespace std;
int split(int split);
int largestprimefactor(priority_queue<int> myints);
int main()
{
int response = 2;
do{
priority_queue<int> myints;
int number;
cout << "Please enter a number: ";
cin >> number;
myints.push(number);
int lcf = largestprimefactor(myints);
cout << endl << "Largest prime factor is: " << lcf;
cout << endl << "Again?(1 for yes 2 for no): ";
cin >> response;
}while(response == 1);
}
uint64_t split(uint64_t split)
{
if(split%2 != 0)
{
if((split/2))%2 == 0)
for(uint64_t i = (split/2)-1; i>1; i=i-2)
if(split%i == 0)
return i;
else
for(uint64_t i = (split/2); i>1; i=i-2)
if(split%i == 0)
return i;
return 1;
}
else
return 2;
}
int largestprimefactor(priority_queue<int> myints)
{
// largestfactor holds the next number to be tested for primeness in the queue
do{
int largestfactor = myints.top();
myints.pop();
//splat will hold the first factor split finds of the top item in the queue
int splat = split(largestfactor);
//if it holds a 1 then that means that there are no factors
if(splat != 1 && largestfactor)
{
myints.push(splat);
myints.push(largestfactor / splat);
}
else
return largestfactor;
}while(myints.top() > 1);
}
Have you considered that 600851475143 is too large to store in a 32 bit int?
Look into what your compiler provides for 64 bit integer types.
I might not be able to help you optimize your code (I'm not sure what you do in split), but here's an idea.
By the fundamental theorem of arithmetic, each number has a unique factorization into a product of primes. This means we can take a number and successively divide it by its prime factors until we reach 1. The last prime factor is the answer.
Now, you need only check prime factors up to sqrt(N). Note that this does not mean that the largest prime factor is less than sqrt(N), but that if there is a prime factor greater than sqrt(N), there is only one such prime factor.
This leads to the following O(sqrt(N)) algorithm:
long long largest_factor(long long number) {
long long result = 0;
for (long long i = 2; i * i <= number; ++i) {
if (number % i == 0) {
result = i;
while (number % i == 0)
number /= i;
}
}
if (number != 1)
return number;
return result;
}
Running this on 600851475143 gives me the right answer.
600851475143 >> 32 give 129, 600851475143 >> 64 give 3.10^-8. This number is too big to be represented as an int, but you can represent it with a 64 bit number as long long or a class designed to represent bigger integers.
/*
The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143 ?
*/
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
int main()
{
unsigned long num = 600851475143;
unsigned long i;
long double root = sqrt(num);
long double tempRoot = 0;
unsigned long factor = 0;
unsigned long largest = 0;
for (i=2; i<root; i++)
{
if (num%i == 0)
{
num = num/i;
factor = i;
cout << factor << endl;
if (factor > largest)
{
largest = factor;
}
}
}
cout << largest << endl;
return 0;
}
This solution works because coincidentally the factors of 600851475143 are all prime numbers. But when debugging the code I was inputting various values for the variable num (=600851475143). For example, when I input 135 it showed me all the factors, including the non-prime ones. How do I add a prime number checker for the factors? I tried using the same method that I used here within a nested if, but failed miserably. Any help would be appreciated.
Also, please indicate if I am using unnecessarily large variable types in case of some variables.
Thanks.
You don't have to do a prime-number check. As you are factoring, just make sure to continue dividing out a candidate until it no longer divides the number. This is really easy to do in code: just change the if (num%i == 0) to while (num%i == 0).