I have this simple program:
// Include libraries
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// Include locals
// Start
#define NUMBER 600851475143
int main(int argc, const char* argv[])
{
long long int ans = 0;
long long int num = NUMBER;
vector<int> factors;
do
{
// Get lowest factor
for (int i = 1; i <= num; ++i)
{
if (!(num % i))
{
factors.push_back(i);
num /= i;
break;
}
}
} while (num > 1);
cout << "Calculated to 1.\n";
int highestFactor = numeric_limits<int>::min();
for (int i = 0; i < factors.size(); ++i)
{
if (factors[i] > highestFactor)
{
highestFactor = factors[i];
}
}
ans = highestFactor;
cout << ans << endl;
return EXIT_SUCCESS;
}
compiling with g++ -O2 -c -o prob3.o prob3.cpp proved successful, but when I ran it I saw nothing and it just kept running and I had to Ctrl-C (force-kill) it in the end. When I try to add
int main(int argc, const char* argv[])
{
cout << "Test\n";
to the program, Test didn't get printed too. It's like my program is not executed at all.
Any help or advice is appreciated!
Solution
I forgot prime numbers started at 2. Change for (int i = 1 to for (int i = 2.
Those nested loops are going to loop forever. The inner for loop will only ever execute once because of the break so it will only ever do num /= 1. That means num never decreases and so num > 1 will never be false. I suppose you just need to wait longer!
The reason you're not seeing "Test" is probably because you haven't flushed the output. Try:
std::cout << "Test" << std::endl;
Your program is simply running. It takes a long time to execute.
For the cout << "Test\n";, it's a matter of the cout stream not being flushed: what you wrote to the stream is still in your program memory and not yet flushed to the system to be printed.
Have you tried to start your for condition from 2? The module function doesn't have sense if start from 1.
if (!(num % i))
Num / 1 give 0, so you're not enter in the if condition
Your loop is an infinite loop. The first factor you find is 1 (since num % 1 is 0) and as such you divide num by 1 which results in num which re-enters the for loop, which does the same again and again.
Also with this fixed (initialize i in the loop with 2), your inner for loop is most likely an infinite loop and/or causing UB. Otherwise (as the others stated) it is "just" running very long. For the case where it is different (assuming most common platforms here). This depends on the value you are trying to factor, if the first factor is smaller than std::numeric_limits<int>::max() then this does not apply. Lets call those primes BIGPRIME (600851475149 would be a good example).
long long int is at least 64bit in size. int is unlikely to be bigger than 32bit on most platforms, so when it is not bigger on your platform it can only go up to std::numeric_limits<int>::max() which is (again assuming the common 32bit platform here) 2147483647 which is in turn promoted in the comparison to long long int but keeps its value, which is always smaller than BIGPRIME. Always increasing i does never get anywhere, and once you are at max() you enter UB land as signed integers don't wrap in C++. Your code might infinite loop there, or do some things like recording -1 as a valid factor, or make you pregnant.
You can easily observe that by adding some
if( 0 == (i%100000000)){ std::cout << i << std::endl; }
into the for loop.
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.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
The program I've written is supposed to take in two user inputs (one being the number we're meant to check whether it's k-hyperperfect or not, the other being a maximum k-value.) if the input integer is k-hyperperfect in the range of 1 to the inputted maximum k-value, then the output should be that k-value. For example, if the input integer is 21 and the maximum k-value is 100 then the output should be 2.
My program gives the correct output for (the first number is the input integer, the second number is the k-max value, the third number is output value) ...
21 (input integer) 100 (k-max) --> 180
301 100 --> 6
12211188308281 100 --> 0
-301 100 --> 0
21 -5 --> 0
However, it doesn't correctly execute for 12211188308281 and 200 (it gives me 0 when it should give me 180). I've run my code through a step by step visualizer and it seems to just abruptly stop execution when i = 496 in the for loop within the else statement. But I don't understand why since it executes correctly for 5 other test runs.
#include <iostream>
using std::cout; using std::cin; using std::endl; using std::fixed;
int main () {
int number;
int kmax;
int sum = 0 ;
int hyper = 0;
std::cin >> number;
std::cin >> kmax;
if (number <= 6 or kmax < 1) {
std::cout << "0" << "\n";
}
else {
for (int i=1;i<=number;i++) {
if (number%i==0 and i != 1 and i != number){
sum+= i;
}
}
}
for (int k=1; k <= kmax; k++) {
hyper = ((sum)*k) + 1;
if (hyper == number) {
std::cout << k << endl;
break;
}
}
}
You need to check that numbers read through std::istreams (like std::cin) are read successfully. As the value that you enter for number is too large to store in an integer your read will fail. For example you could change your code to:
int main()
{
int number;
std::cin >> number;
if ( !std::cin )
{
std::cout << "invalid value: " << number << "\n";
return 1;
}
else
{
std::cout << "valid value: " << number << "\n";
}
// calculate answer
return 0;
}
You would then see your program printing "invalid value: 2147483647" if you have a c++11 compliant compiler or an undefined number if you have an older compiler.
Now that you have implemented reading values correctly the fix to your issue is to use a larger integer type like int64_t which is able to hold your number.
As already noted, the int type in your machine isn't big enough to store the value 12,211,188,308,281.
The C++ standard only mandates it to be capable of storing a value up to 32,767 and even in the (now common) case of a 32-bit int or long int), the limit would be 2,147,483,647. So you need a long long int or an int64_t (if it's present in your implementation).
A simple check like
if (std::cin >> number >> kmax ) { // perform calculations...
Would have shown the error sooner.
That beeing said, there are also some simple changes that could be done to the posted code in order to make it more efficient. The first loop can be optimized considering the "symmetry" of the divisors of a given number: meaning, if n is divisible by a, so that b = n/a is a whole number, b too is a divisor of n. This will limit the number of iterations to the square root of n, instead of n.
long long int number,
kmax,
sum = 0;
// ...
long long int temp = number,
i = 2;
for (; i * i < number; i++) {
if (number % i == 0) {
temp = number / i;
sum += i + temp;
}
}
if (i * i == number) {
sum += i;
}
There probably are better algorithms, but I'm unfamiliar with those.
The second loop, in my opinion, is unnecessary. The value k can be calculated directly:
if ( (number - 1) % sum == 0) {
std::cout << (number - 1) / sum << '\n';
}
You are assigning a too long value 12211188308281 to integer "number", which can't contain it fully and it is getting truncated to 596285753. You can add a print statement to print it.
std::cout<<number;
which will print 596285753.
As suggested you should use long long int. Again its dependent on the software platform running on your system.
The code that I did was for solving the following problem. However, the logic of the code is wrong and I as a good newbie cannot figure what is wrong.
After I compile the result of 'sum' is always 0, if I change the initialization of 'sum' for a whatever number, that whatever number is what appear as answer of 'sum'.
If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
Find the sum of all the multiples of 3 or 5 below 1000.
#include <iostream>
using std::cout;
using std::endl;
int main()
{
long sum = 0;
for( long i; i < 1000; ++i )
{
if (( i % 3 == 0 ) || ( i % 5 == 0 ))
{
sum = sum + i;
}
}
cout << "The sum is: " << sum << endl;
return 0;
}
You need to initialize i in your loop:
for (long i = 0; i < 1000; ++i )
As it is, i is probably some random number greater than 0 at the top of the loop, and the result is that the loop is never executed.
You need to initialize i to zero otherwise i's value will be whatever happens to be in memory. In this case it's > 1000.
for (long i = 0; i < 1000; ++i)
Also, a nice trick I learned. Use ii as your index variable. It's much easier to find ii than just i in your code.
You forgot to set i=O in your loop so the loop won't iterate.
All answers above are correct - you need to set your i to 0. What you might be interested in is that accessing uninitialized variable is an "undefined behaviour" (UB) and modern compilers are actually pretty good in finding the UBs and using them to optimize the code. For example, GCC 5.2 with -O2 (optimizations enabled) will generate same assembly for your code and for one without the loop at all regardless of what might happen to be in the memory at the address of i.
Try putting this code to (which is your code with additional #if for convenience) this online disassembler
#include <iostream>
using std::cout;
using std::endl;
int main()
{
long sum = 0;
#if 1
for (long i; i < 1000; ++i)
{
if ((i % 3 == 0) || (i % 5 == 0))
{
sum = sum + i;
}
}
#endif
cout << "The sum is: " << sum << endl;
return 0;
}
add the -O2 flag to compiler options on top right and try changing #if 1 to #if 0 and observe that the disassembly is the same meaning that the compiler cut out the loop completely.
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);
}
I'm working on Euler Problem 14:
http://projecteuler.net/index.php?section=problems&id=14
I figured the best way would be to create a vector of numbers that kept track of how big the series was for that number... for example from 5 there are 6 steps to 1, so if ever reach the number 5 in a series, I know I have 6 steps to go and I have no need to calculate those steps. With this idea I coded up the following:
#include <iostream>
#include <vector>
#include <iomanip>
using namespace std;
int main()
{
vector<int> sizes(1);
sizes.push_back(1);
sizes.push_back(2);
int series, largest = 0, j;
for (int i = 3; i <= 1000000; i++)
{
series = 0;
j = i;
while (j > (sizes.size()-1))
{
if (j%2)
{
j=(3*j+1)/2;
series+=2;
}
else
{
j=j/2;
series++;
}
}
series+=sizes[j];
sizes.push_back(series);
if (series>largest)
largest=series;
cout << setw(7) << right << i << "::" << setw(5) << right << series << endl;
}
cout << largest << endl;
return 0;
}
It seems to work relatively well for smaller numbers but this specific program stalls at the number 113382. Can anyone explain to me how I would go about figuring out why it freezes at this number?
Is there some way I could modify my algorithim to be better? I realize that I am creating duplicates with the current way I'm doing it:
for example, the series of 3 is 3,10,5,16,8,4,2,1. So I already figured out the sizes for 10,5,16,8,4,2,1 but I will duplicate those solutions later.
Thanks for your help!
Have you ruled out integer overflow? Can you guarantee that the result of (3*j+1)/2 will always fit into an int?
Does the result change if you switch to a larger data type?
EDIT: The last forum post at http://forums.sun.com/thread.jspa?threadID=5427293 seems to confirm this. I found this by googling for 113382 3n+1.
I think you are severely overcomplicating things. Why are you even using vectors for this?
Your problem, I think, is overflow. Use unsigned ints everywhere.
Here's a working code that's much simpler and that works (it doesn't work with signed ints however).
int main()
{
unsigned int maxTerms = 0;
unsigned int longest = 0;
for (unsigned int i = 3; i <= 1000000; ++i)
{
unsigned int tempTerms = 1;
unsigned int j = i;
while (j != 1)
{
++tempTerms;
if (tempTerms > maxTerms)
{
maxTerms = tempTerms;
longest = i;
}
if (j % 2 == 0)
{
j /= 2;
}
else
{
j = 3*j + 1;
}
}
}
printf("%d %d\n", maxTerms, longest);
return 0;
}
Optimize from there if you really want to.
When i = 113383, your j overflows and becomes negative (thus never exiting the "while" loop).
I had to use "unsigned long int" for this problem.
The problem is overflow. Just because the sequence starts below 1 million does not mean that it cannot go above 1 million later. In this particular case, it overflows and goes negative resulting in your code going into an infinite loop. I changed your code to use "long long" and this makes it work.
But how did I find this out? I compiled your code and then ran it in a debugger. I paused the program execution while it was in the loop and inspected the variables. There I found that j was negative. That pretty much told me all I needed to know. To be sure, I added a cout << j; as well as an assert(j > 0) and confirmed that j was overflowing.
I would try using a large array rather than a vector, then you will be able to avoid those duplicates you mention as for every number you calculate you can check if it's in the array, and if not, add it. It's probably actually more memory efficient that way too. Also, you might want to try using unsigned long as it's not clear at first glance how large these numbers will get.
i stored the length of the chain for every number in an array.. and during brute force whenever i got a number less than that being evaluated for, i just added the chain length for that lower number and broke out of the loop.
For example, i already know the Collatz sequence for 10 is 7 lengths long.
now when i'm evaluating for 13, i get 40, then 20, then 10.. which i have already evaluated. so the total count is 3 + 7.
the result on my machine (for upto 1 million) was 0.2 secs. with pure brute force that was 5 seconds.