C++ Prime factor program 2 problems - c++

Okay so I"m writing a program (in C++) that is supposed to take a number, go through it, find out if it's factors are prime, if so add that to a sum, and then output the sum of all of the imputed number's prime factors.
My program successfully seems to do this however it has 2 problems,
1) The number I am supposed to test to see the sum of the prime factors of this number (600851475143) but it's too big for an int. I'm not sure what other variable type to use, or which variable's types to change. I would really like a clear explanation on this if at all possible.
2) For some reason, when the program checks to see if 1 is a factor of the number, and then checks to see if 1 is prime, it says 1 is prime, even though the first step of the function for checking to see if it's prime is that if it's 1 then it isn't prime. I found a fix for this, by telling it to subtract 1 from the very last value for the sum of all prime factors. However, this is a fix, not really finding the problem. If someone could point out at least where the problem is I would appreciate it!
Here's the code, if you have questions, please ask!
#include <iostream>
using namespace std;
bool prime (int recievedvalue) { //starts a function that returns a boolean with parameters being a factor from a number
int j =1;
int remainderprime = 0;
bool ended = false;
while (ended == false){ //runs loop while primality is undetermined
if (recievedvalue == 1){ //if the recieved value is a 1 it isn't prime
//not prime
break; // breaks loop
return false;
}
remainderprime=recievedvalue%j; //gives a remainder for testing
if ((remainderprime==0 && j>2) && (j!=recievedvalue || j == 4)){ //shows under which conditions it isn't prime
ended=true;
//not prime
return false;
}
else if (j==1){
j++;
}
else if ( recievedvalue==2 || j==recievedvalue ){ // shows what conditions it is prime
ended = true;
//prime
return true;
}
else {
j++;
}
}
}
int multiple(int tbfactor){ //factors and then checks to see if factors are prime, then adds all prime factors together
//parameter is number to be factored
int sum = 0;
bool primetest = false;
int remainderfact;
int i=1;
while (i<=tbfactor){ //checks if a i is a factor of tbfactor
remainderfact=tbfactor%i;
if (remainderfact==0){ //if it is a factor it checks if it is a prime
primetest = prime(i);
}
if (primetest ==true){ //if it is prime it add that to the sum
sum += i;
primetest=false;
}
i++;
}
sum --; // for some reason it always ads 1 as a prime number so this is my fix for it
return sum;
}
int main()
{
int input;
int output;
cout << "Enter number to find the sum of all it's prime factors: ";
cin >> input;
output = multiple(input);
cout << output;
return 0;
}
I'm really new to this, like a few days or so, so I'm very unfamiliar with stuff right now so please explain easily for me! I look forward to your help! Thanks!

For 1), you need to use a larger datatype. A 64-bit integer should be enough here, so change your ints to whatever the 64-bit integer type is called on your platform (probably long, or maybe long long).
For 2), the problem appears to be that you have a break before your return false. The break causes the code to stop the while loop immediately and continues execution immediately after the loop. It doesn't appear that the return value is ever assigned in that case (which your compiler should be warning you about), so the actual value returned is effectively arbitrary.

While others have pointed out a problem with your data types, there's a few problems with the structure of the first function that immediately caught my eye. (BTW, your indentation is enraging.) Look at this stripped-down version:
bool prime (int recievedvalue) {
// ...
bool ended = false;
while (ended == false){
if (...){
break; // jumps _behind_ the loop
return false;
}
// ...
if (...) {
ended=true;
return false; // leaves function returning true
}
else if (...) {
// ...
}
else if (...) {
ended = true;
return true; // leaves function returning false
}
else {
// ...
}
}
// behind the loop
// leaves function returning random value
}
For one, every time you set the loop control variable ended, you leave the loop anyway using some other means, so this variable isn't needed. A while(true) or for(;;) would suffice.
Also, that break jumps behind the loop's body, but there isn't a statement there, so the code leaves the function without explicitly returning anything! That's invoking so-called Undefined Behavior. (According to the C++ standard, your program is, from this point on, free to do whatever it pleases, including returning random values (most implementations will do that), formatting your HD, invoking nasty Nasal Demons on you, or returning exactly what you expected, but only on Sundays.)
Finally, that break occurs right before a return false; which is therefor never reached. Actually your compiler should warn about that. If it doesn't, you're likely not compiling at the highest warning level. (You should turn this on. Always try to cleanly compile your code at the highest warning level.) If it does, learn to pay attention to compiler warnings. They are a very important tool for diagnosing problems during compilation. (Remember: Errors diagnosed during compilation need no testing and never make it to the customer.)

Use either a 64 bits number on a 64 bits system, or use a library that does arbitrary precision arithmetic
Remove the break before the return false. Because of the break, execution is resumed outside the loop and return false is never executed.

To store values larger than 4 bytes (the capacity of an int) you have a variety of options. Refer to this page for those options. As to why you're program is returning true for the check on whether or not 1 is prime, check out this section of code:
if (recievedvalue == 1){ //if the recieved value is a 1 it isn't prime
//not prime
break; // breaks loop
return false;
}
The break statement will exit and return false will never be reached. To solve the problem, remove the break statement.

Related

Recursive functions in winning number

I need to make a code that checks if parameter r is a winner.
int is_winner(const float r){
}
You could try something like the following.
if (r <= max_winner && r => 0) {
if (/* simple criterion */) { // i.e. whole game even
return true;
} else if ( /* recursive call */ ){ // recursion, i.e. r/2 is winner and r*r is winner
return true;
}
}
Note that I assume (for sake of simplicity) that the output of your function should be a boolean variable, since the function is called is_winner, where we just want to check if it is true or false.
Try to fill in the conditions on your own. Note, that there are functions like std::floor, std::ceil. Also be aware of conversion from float or double to integer; e.g. check the beahviour of
float r = 2.7189;
int r_int = r;
(I'm not giving code because I think this is an exercise that you should make yourself)
In this particular exercise, it is harder to understand what the required test actually is than to implement it after a lesson on recursive functions.
Basically, if the number is within the range and the integer part of the number is not even, check its half and its square until one of them goes out of limit or is even by calling is_winner() for both from within is_winner() and pass the result back (both should be winners) until you know that the given number is a winner or not.
I would print results in the function to see what is going on.
I guess, since 0 is part of the range, half is always a winner if the number is within the range.

When to return from a function?

Sorry in advance if the question sounds naive. I am writing a simple bool function to check if all digits of a number are same. The following works, however the one after, gives me an error of
17:1: warning: control reaches end of non-void function [-Wreturn-type]
What I am doing wrong with the second one?
Working:
# include <iostream>
# include <string>
using namespace std;
bool samedigits (int number){
bool result = true;
std::string snumber = to_string (number);
for (int i=0; i < snumber.size(); i++){
if (snumber[i] != snumber[0]){
result = result and false;
break;
}
}
return result;
}
int main()
{
cout << samedigits (666);
return 0;
}
Non working:
# include <iostream>
# include <string>
using namespace std;
bool samedigits (int number){
std::string snumber = to_string (number);
for (int i=0; i < snumber.size(); i++){
if (snumber[i] != snumber[0]){
return false;
break;
}
return true;
}
}
int main()
{
cout << samedigits (666);
return 0;
}
Your algorithm is incorrect, you are only checking if the first character is equal to itself, and returning true for every input. Instead, you should move the return true outside the loop, so that you check all the characters first.
Unfortunately, the warning is a false positive. The compiler fails to realize that std::to_string is guaranteed to return a non-empty string when passed an int. This means that the for loop body will be entered, and the function will return a value.
The compiler is right. There is a code path in your second snippet that won't return.
for (int i=0; i < snumber.size(); i++){
Here, the std::string size function can return 0 according to its contract. When it does happen, then your function won't enter the loop. After that, you exit the function without returning.
The second version of your function (combined with some information obtained via comments) indicates a misunderstanding of what return does. The second version would work (here is the misunderstanding) if a return statement were to simply store the indicated value for use when the function eventually ends. However, this is not how return works. A return statement stores the indicated value for use when the function ends and immediately ends the function. In the second version of your function, the for statement might as well be an if and the break is never executed as it comes right after a return.
To demonstrate, let's do a code walk-through for a call to samedigits(123).
bool samedigits (int number){
As we enter the function, number is set to 123.
std::string snumber = to_string (number);
The string snumber is set to "123".
for (int i=0; i < snumber.size(); i++){
The loop initializes by setting i to 0 then checks if 0 < 3 (the size of snumber is 3). This is true, so we enter the loop. Note that the result of entering the loop depends only on snumber not being empty.
if (snumber[i] != snumber[0]){
We check to see if snumber[0] does not equal snumber[0]. This is a bit trivial, but the computer is willing to do it. The result, of course, is false (independent of what the input was – this part might be more interesting if the loop started at 1 instead of 0). So skip to the statement after the if.
return true;
The function immediately ends, returning true.
And that's it. There is no second iteration of the loop. No other code is executed during this function call. Since to_string never returns an empty string, the second version of your function is functionally equivalent to the following:
bool samedigits (int /*number*/){
return true;
// Execution ends with the return statement, so nothing after
// this comment ever executes.
std::cout << "This is dead code. It will never execute.\n";
std::cout << "You will never see this output.\n";
}
To fix the second version, you need to return inside the loop only when the if condition is true. Move return true; to be after the loop so that the loop can iterate multiple times. You do not want to end the function and tell the caller that all the digits are the same (which is what return true; does) until after you've checked all the digits. (If your loop finds a mismatch, execution will reach the return false; inside the loop. At that point, the function ends, so code after the loop has no effect on that function call.)
A smaller (cosmetic) fix is to get rid of the break. Suppose the loop did iterate enough times to find a mismatch. Execution would go into the if statement body and encounter return false. At that point, not only is the loop stopped, but the function as a whole ends, before the break statement is seen. The break statement is dead code, meaning code that can never be executed. In order to get to the break, execution has to go through a return. Execution may arrive at a return statement, but it never goes through one.
Also, be sure to thank your compiler for finding this error, as it does point to a bug in your code. It's not the exact bug the compiler reported, but then again, compilers are not exactly the best thinkers in the world. :)

Comparing double error C++

recently I bump into a problem while comparing a double in an if statement. I was trying to cout the number of whole numbers in a double. Being a beginner, I am not sure what gone wrong in my code.
This is my code:
#include <iostream>
using namespace std;
int main(){
int x=0;//convert double to int
long double Out;//Result
long double In=10;//Input double
//Loop Begin
while(In>0){
x=In;//convert double to int
Out= (x/In);//Out(test if whole number, will return 1)
//test for 1
////////////////
if(Out == 1 ){
cout<<"[Whole Number] ";
}
////////////////
//test end
cout<<"In :"<<In<<", ";
cout<<"X :"<<x<<", ";
cout<<"Out :"<<Out<<endl;
In-=0.1;//decrease to finish loop (eventually)
}
//Loop End
cin.get();
return 0;
}
This program will test and output the whole numbers in the double (In). I realized that the accuracy of the double was affecting the if statement which is why I can't get the "[Whole Number]" result. Although I found out that if I used (0.9999) in "if(Out >= 0.9999)" the comparison would work. But I am not sure of a solution, please help! Much appreciated!
Your while loop never stops , its a infinite loop . You are not doing anything with the value of "In" in the while loop hence it will always be greater than 0 ,therefore a infinite loop .
You should probably approach the problem more directly with modf:
double int_part, frac_part;
frac_part = std::modf(in, &int_part);
if (frac_part == 0) {
// int_part contains integer value.
} else {
// process the double non-integer floating point value.
}
Your code works perfectly fine. If you subtract 0.1 from 10.0, then chances are that the result is not an integer due to rounding errors, and your code tells you exactly that. The code isn't wrong, your expectations are wrong.
if (Out >= 0.9999)
is obviously not a solution, because it will always be true if In >= 10000.0.
Do to the way floating point numbers are converted to binary representation by the computer they are inherently inaccurate and thus make logical comparisons somewhat challenging (http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems). When performing such comparisons to floating point numbers you typically will do so utilizing an epsilon constant (http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm) that represents the maximum acceptable error in the comparison. In your case you need to select a suitable value for epsilon (say .000001). Then change your comparison to:
if(abs(out - 1) < epsilon){ //Take the difference between out and 1
cout<<"[Whole Number]"; //If it is "close enough" print to console
}
I am more of a Java guy but I believe you will need #include stdlib.h to utilize the abs() function.
Hope that helps!
Try using the modulus operator: http://www.cprogramming.com/tutorial/modulus.html
Something like if(In % 1 == 0) should work.

Learning C++, looking for a clarification on this project from a book

The goal here was to create a program that found and output all the prime numbers between 1 and 100. I've noticed I have a tendency to complicate things and create inefficient code, and I'm pretty sure I did that here as well. The initial code is mine, and everything that I've put between the comment tags is the code given in the book as a solution.
// Find all prime numbers between 1 and 100
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int counter; // loop counter
int count_two; // counter for second loop
int val; // equals the number of count, used in division to check for primes
bool check;
check = true;
for(counter = 1; counter <= 100; counter++){
val = counter;
for(count_two = 2; count_two <= 9; count_two++){
if((val % count_two) == !(check)){
cout << val << " is a prime number.\n";
}
}
}
return 0;
}
// program didn't work properly because of needless complication; all that needs to be checked for is whether a number is divisible by two
/*
*********correct code***********
#include <iostream>
using namespace std;
int main()
{
int i, j;
bool isprime;
for(i=1; i < 100; i++) {
isprime = true;
// see if the number is evenly divisible
for(j=2; j <= i/2; j++)
// if it is, then it is not prime
if((i%j) == 0) isprime = false;
if(isprime) cout << i << " is prime.\n";
}
return 0;
}
********************************
*/
From what I can gather, I was on a reasonably correct path here. I think I complicated things with the double loop and overuse of variables, which probably led to the program working incorrectly -- I can post the output if need be, but it's certainly wrong.
My question is basically this: where exactly did I go wrong? I don't need somebody to redo this because I'd like to correct the code myself, but I've looked at this for a while and can't quite figure out why mine isn't working. Also, since I'm brand new to this, any input on syntax/readability would be helpful as well. Thanks in advance.
As it is, your code says a number is prime if it is divisible by any of the numbers from 2 to 9. You'll want a bool variable somewhere to require that it's all and not any, and you'll also need to change this line:
if((val % count_two) == !(check)){
Since check = true, this resolves as follows:
if ((val % count_two) == !true){
and
if ((val % count_two) == false){
and
if ((val % count_two) == 0){
(Notice how the value false is converted to 0. Some languages would give a compile error here. C++ converts it into an integer).
This in fact does the opposite of what you want. Instead, write this, which is correct and clearer:
if (val % count_two != 0) {
Finally, one thing you can do for readability (and convenience!) is to write i, j, and k instead of counter, count_two, and count_three. Those three letters are universally recognized by programmers as loop counters.
In addition to the points made above:
You seemed to think you didn't need to have 2 loops. You do need them both.
Currently, in your code, the upper range of the inner loop is in-dependent on the value of your outer loop. But this is not correct; you need to test divisibility up the the sqrt(outer_loop_value). You'll note in your "correct" code they use half of the outer_loop_value - this could be a performance trade off but strictly speaking you need to test up to sqrt(). But consider that your outer loop was up to 7, your inner loop is testing division all the way up to 9 and 7 is in that range. Which means 7 would be reported as not prime.
In your "correct" code the indenting makes the code harder to interpret. The inner for loop only has a single instruction. That loop loops through all possible divisors. This is unnecessary it could break out at the first point that the mod is zero. But the point is that the if(isprime) cout << i << " is prime.\n"; is happening in the outer loop, not the inner loop. In your (un-commented) code you have put that in the inner loop and this results in multiple responses per outer loop value.
Stylistically there is no need to copy the counter into a new val variable.

C++ Sieve of Eratosthenes finding 3 too many primes

I have a programming assignment to write a program in C++ that finds all primes less than n (user input). One half of the assignment involves the Sieve of Eratosthenes. My code is working (read: assignment is complete), but before I edited the output, it was unconditionally printing out n-3, n-2, and n-1 as primes even if they were not prime. I'm not sure why this is happening. I'd appreciate a bit of feedback and ideas as to why the program is acting the way it is. Here is the unaltered code:
Please note that I am using a ListNode class and a LinkedList class, both of which are fully functional. EDIT: partial main added; notice the second item in the for loop is size-3. If it's left at size, the program outputs 3 extra non-primes.
int main()
{
for(int i = 0; i<my_list.size()-3; i++)
{
if(marked[i]==true)
cout<<my_list[i]<<"\n";
}
}
void eratosthenes(int item)
{
bool run=true;
int p=2, count=0;
for(int i=2; i<=item; i++)
{
my_list.append(i); // Entire list is filled with integers from 2 to n
marked.append(true); // Entire list is filled with true entries
}
while(run==true&&(2*p)<item)
{
count = 0;
int i = (2*p);
do {
marked[i-2]=false; // marked values are false and not prime
i+=p;
} while(i<item-2);
for(int i=0; i<item-2; i++) // i starts at 0 and increments by 1
{ // each time through the loop
if(my_list[i]>p)
{
if(marked[i]==true) // If a value stored in a node is true
{ // (prime), it becomes the new p.
p=my_list[i]; // The loop is then broken.
break;
}
}
}
for(int j=1; j<item-2; j++)
{
if(marked[j]==false)
{
count=1;
}
}
if(count==0)
run=false;
}
Complete method
void Eratosthenes(int upperBound)
{
bool Prime[upperBound];
for(int i = 0;i<upperBound;i++)
Prime[i]=true;
for (int i = 2; i <= sqrt(upperBound); i++)
{
if (Prime[i])
{
for (int j = i * 2; j < upperBound; j += i)
Prime[j] = false;
}
}
for(int i=2;i<upperBound;i++)
{
if(Prime[i]==true)
cout<<i<<" ";
}
}
From your code:
do{
marked[i-2]=false;//marked values are false and not prime
i+=p;
}while(i<item-2);
This loop is responsible for going through all numbers i that are integer multiples of the prime number p and marking them not prime, as I understand. Why are you stopping on the condition i < item - 2? This would be fine if i were your index for the my_list and marked lists, but in this case it's not; it's the actual number you're marking not prime. I suspect this is why you're getting numbers near your limit (item) that are marked as prime—your loop here exits before i ever gets to those numbers!
By the way, you could do this as a for loop instead, which would be easier to read. The for loop has the meaning "go through each element in a set" (whether that's consecutive integers, or every nth integer, or elements in an array/list/deque, etc.), so a programmer reading your code knows that immediately and doesn't have to figure it out from your while loop.
// mark every multiple of the current prime as not prime
for(int i = 2*p; i < item - 2; i += p)
{
marked[i-2] = false;
}
(This is the same as your original code, no fixes applied).
Some general comments to improve your algorithm/code:
Try using more descriptive variable names. Your use of i two times to mean different things is confusing, and in general single letters don't mean much as to what the variable represents (although sometimes they're sufficient, e.g. a for loop where i is the index of a list/array).
Also, you're looping over your list a lot more than you need to. The minimum a sieve of Eratosthenes algorithm needs is two nested for loops (not including initializing a list/array to all true).
One example of where you're doing more work than necessary is that you're looping starting from index 0 to find the next p to use—instead of just remembering where your current p is and starting from there. You wouldn't even need to check my_list[i] > p in that case, since you know you'd be beyond it to start off. Also, your last loop could break; early and avoid continuing on after it finds a non-prime (and I'm not sure what the point of it is).
Nikola Mitev's second answer is a more efficient and more readable implementation of the sieve (but replace sqrt(upperBound) with upperBound/2 for it to work correctly; the reason for upperBound/2 should be pretty clear from the way the Sieve works), although he didn't really give much comment or explanation on it. The first loop is "go through every number up to upperBound"; inside it, "if the current number is a prime, go through all the multiples of that prime and mark them non-prime". After that innerloop executes, the outer loop continues, going through the next numbers—no need to start from the beginning, or even type out another for loop, to find the next prime.
EDIT: sqrt(upperBound) is correct. I wasn't thinking about it carefully enough.
Why don't you work with array of booleans for simplicity starting from index 2, and when you will print the result, you will print indices with value of true