C++ program doesn't fully execute iteration [closed] - c++

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.

Related

C++ , cout line in function effects the result, function does not work without cout line

I'm trying to solve Codewars task and facing issue that looks strange to me.
Codewars task is to write function digital_root(n) that sums digits of n until the end result has only 1 digit in it.
Example: 942 --> 9 + 4 + 2 = 15 --> 1 + 5 = 6 (the function returns 6).
I wrote some bulky code with supporting functions, please see code with notes below.
The problem - digital_root function works only if I put cout line in while loop. The function returns nonsense without this cout line (please see notes in the code of the function).
My questions are:
Why isn't digital_root working without cout line?
How cout line can effect the result of the function?
Why does cout line fix the code?
Thanks a lot in advance! I'm a beginner, spent several days trying to solve the issue.
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
int getDigit (int, int);
int sumDigits (int);
int digital_root (int);
int main()
{
cout << digital_root (942); // expected output result is 6 because 9 + 4 + 2 = 15 -> 1 + 5 = 6
}
int getDigit (int inputNum, int position) // returns digit of inputNum that sits on a particular position (works)
{
int empoweredTen = pow(10, position-1);
return inputNum / empoweredTen % 10;
}
int sumDigits (int inputNum) // returns sum of digits of inputNum (works)
{
int sum;
int inLen = to_string(inputNum).length();
int i = inLen;
while (inLen --)
{
sum += getDigit(inputNum, i);
i --;
}
return sum;
}
int digital_root (int inputNum) // supposed to calculate sum of digits until number has 1 digit in it (abnormal behavior)
{
int n = inputNum;
while (n > 9)
{
n = sumDigits(n);
cout << "The current n is: " << n << endl; // !!! function doesn't work without this line !!!
}
return n;
}
I've tried to rewrite the code from scratch several times with Google to find a mistake but I can't see it. I expect digital_root() to work without any cout lines in it. Currently, if I delete cout line from while loop in digital_root(), the function returns -2147483647 after 13 seconds of calculations. Sad.
Here is an implementation using integer operators instead of calling std::to_string() and std::pow() functions - this actually works with floating-point numbers. It uses two integer variables, nSum and nRem, holding the running sum and remainder of the input number.
// calculates sum of digits until number has 1 digit in it
int digital_root(int inputNum)
{
while (inputNum > 9)
{
int nRem = inputNum, nSum = 0;
do // checking nRem after the loop avoids one comparison operation (1st check would always evaluate to true)
{
nSum += nRem % 10;
nRem /= 10;
} while (nRem > 9);
inputNum = nSum + nRem;
std::cout << "The current Sum is: " << inputNum << endl; // DEBUG - Please remove this
}
return inputNum;
}
As for the original code, the problem was the uninitialized sum variable, as already pointed out by other members - it even generates a compiler error.
int sumDigits (int inputNum) // returns sum of digits of inputNum (works)
{
int sum = 0; // MAKE SURE YOU INITIALIZE THIS TO 0 BEFORE ADDING VALUES TO IT!
int inLen = to_string(inputNum).length();
int i = inLen;
while (inLen --)
{
sum += getDigit(inputNum, i);
i --;
}
return sum;
}
Initialize your variables before adding values to them, otherwise you could run into undefined behaviour. Also for the record, adding the cout line printed out something, but it wasn't the correct answer.

My C++ prime number identifier and prime factor finder has a bug [closed]

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 2 years ago.
Improve this question
I'm a beginner to C++ and this website, so any dumb mistakes are out of ignorance. For practice, I'm trying to write a program that identifies a prime number and gives a composite's prime factors if the user requests. The prime IDer works, but the prime factors do not. When I type in twelve as my number, it gives me the factors 2 3 and 5, and 12's prime factors are 2 2 and 3. What am I messing up? Here is the code. Don't mind the weird spaces or names.
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
//Printing factors help
void print(std::vector<int> const& factors)
{
for (int i = 0; i < factors.size(); i++) {
std::cout << factors.at(i) << ' ';
}
}
int main() {
//Restarting it
std::string again;
again = "Yes";
//Actual loop
while (again == "Yes") {
//Variable/vectors
std::string pfacts;
double input = 0;
double result = 0;
double looper = 2;
int looper2 = 2;
int printed = 0;
int printed2 = 0;
std::vector<int> factors;
std::vector<int> holders;
//Asking for number
std::cout << "Please enter your number.\n";
std::cin >> input;
double holder = input;
//Ratting out trolls
if (input == 0) {
std::cout << "Your number is neither.\n";
looper = 1000003;
}
if (input == 1) {
std::cout << "Your number is neither.\n";
looper = 1000003;
}
//Prime/composite loop
while (looper < 1000002 and input != 1 and fmod(result, 1) == 0) {
result = input / looper;
//Finding composite
if (fmod(result, 1) == 0 and printed == 0) {
std::cout << "Your number is composite.\n";
printed = 1;
looper = 1000003;
}
//Finding prime
else if (fmod(result, 1) != 0 and printed2 == 0) {
std::cout << "Your number is prime.\n";
printed2 = 1;
}
}
//Asking about factors
if (printed == 1) {
std::cout << "Would you like to know it's prime factors? (Please type Yes or No exactly)\n";
std::cin >> pfacts;
}
//Actually finding them
if (pfacts == "Yes") {
while (looper2 < 1000002) {
if (holder / looper2 == 0) {
factors.push_back(holder);
looper2 = 1000003;
}
if (looper2 < 1000002 and fmod (fmod(holder, looper2), 1) == 0 and looper2 % 2 != 0 or looper2 / 2 == 1) {
factors.push_back(looper2);
holder = holder / looper2;
}
looper2 = looper2 + 1;
}
//Printing them
print(factors);
std::cout << "\n";
}
//Again?
std::cout << "Do you need to input another number? (Please type, exactly: Yes or No)\n";
std::cin >> again;
}
}
You're just making a really simple thing more complex with that looper , printed stuff,
a good programmer is one which solves hard things in easy way.
So it is hard to understand for me to know exactly what you're doing in the code above at least not without enough comments.
So here is my solution, i am just providing the algorithm so you can write your own code and learn from it.
First note things below.
A prime number is a positive integer which has exactly two factors first is 1 and another is that number itself , so two is smallest prime number.
A number is also prime if it is not divisible from 2 to its square root, you should consider this fact for performance.
Now the algorithm:
Take the number in a variable num.
Check if it is positive integer greater then 1, if not then it is not a prime.
Take num's squareroot with help of sqrt() function in variable num as you don't need original num any more.
Now add one to num and take its absolute value.
Start a loop from i = 2 to num: you're starting from 2 because two is the smallest prime.
In every iteration check num % i == 0, if yes then it is not a prime and you break, otherwise don't do anything.
Now after the loop ends check if i == num, if yes that means you never broke the hence the number is prime and you're done, otherwise you broke the loop hence the number is not prime and you ask for prime factors.
Now again you start from j = 2 to num.
Now if num % j == 0, you print j and do num = num / j, otherwise you increment j.
I hope it is helpful. I didn't test it on an IDE, because I don't have one because I don't write c++ code anymore. Tell me if you find any bugs.

Can't get my code to divide with decimal precision

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.

program giving wrong output for a specific input

I want to check if a number is prime. Here is my code:
#include <iostream>
using namespace std;
int main(){
int num;
int i, k = 0;
cin >> num;
for(i = 2; i < num; i++){
if(num % i == 0){
k = k + 1;
}
}
if(k > 0){
cout << "The number is not prime" << endl;
}else{
cout << "Prime!" << endl;
}
return 0;
}
When I enter 6 , 78, ... etc it's giving the correct output.
But when I'm entering 4294967296 which is not a prime number, it's returning Prime!.
That's because 4294967296 is a rather special number. It is 2^32, which is limit of the storage capacity of an int, which typically holds only 32 bits. Thus, your num is interpreted as if it were 0.
The rest follows logically from that overflow misinterpretation. The for loop is never entered, since 2 is not less than 0, so k never gets incremented.
EDIT Actually, in this particular case, it fails for a different reason. std::cin performs truncation on the input, so when you enter 4294967296, num will actually get assigned the value of 2147483647. Your program [correctly] prints that that value is prime. It's just that that's not the number the user had intended to test.
You need to validate your input. 4294967296 is too big for 32 bit signed integer, so std::cin truncates it to 2147483647 which is actually prime. You can check that printing your number back to screen. You should also change your loop to:
for(i = 2; i < num / 2; i++)
as it would provide the same result, but decrease calculation time twice.

What is wrong with this C++ code? 3n+1 in programming-challenges/UVa

The Programming-Challenges website marked it as a wrong answer. I checked with sample inputs and they were all correct. I added an optimization to the code, I made it so it doesn't check numbers that are known to be in another number's sequence, since it would be a subsequence and obviously have a shorter cycle length.
Also I just got back into programming so the program isn't too terse but I hope it is readable.
Here is the code:
#include <iostream>
#inclue <vector>
struct record
{
int number;
int cyclelength;
};
void GetOutput(int BEGIN, int END)
{
//determines the output order at the end of function
bool reversed = false;
if (BEGIN > END)
{
reversed = true;
int temp = BEGIN;
BEGIN = END;
END = temp;
}
vector<record> records;
for (int i = BEGIN; i <= END; ++i)
{
//record to be added to records
record r;
r.number = i;
r.cyclelength = 1;
records.push_back(r);
}
int maxCycleLength = 1;
//Determine cycle length of each number, and get the maximum cycle length
for (int i =0;i != records.size(); ++i)
{
//
record curRecord = records[i];
//ABCD: If a number is in another number's sequence, it has a lower cycle length and do not need to be calculated,
//set its cyclelength to 0 to mark that it can be skipped
if (curRecord.cyclelength != 0)
{
//
while (curRecord.number != 1)
{
//next number in the sequence
int nextNumber;
//finds the next number
if (curRecord.number % 2 == 0)
nextNumber = curRecord.number / 2;
else
{
nextNumber = curRecord.number * 3 + 1;
//if nextNumber is within bounds of input, mark that number as skippable; see ABCD
if (nextNumber <= END)
{
records[nextNumber - BEGIN].cyclelength = 0;
}
}
curRecord.number = nextNumber;
curRecord.cyclelength += 1;
}
maxCycleLength = max(curRecord.cyclelength, maxCycleLength);
}
}
if (reversed)
{
cout << END << " " << BEGIN << " " << maxCycleLength;
}
else
{
cout << BEGIN << " " << END << " " << maxCycleLength;
}
}
int main(){
//The first and last numbers
vector< vector<int> > input;
int begin, end;
while (cin >> begin >> end)
{
//storage for line of input
vector<int> i;
i.push_back(begin);
i.push_back(end);
input.push_back(i);
}
for (int i = 0;i != input.size(); ++i)
{
GetOutput(input[i][0], input[i][1]);
cout << endl;
}
return 0;
}
I'll try to give you a hint to nudge you into figuring out the problem.
The sample inputs are good as a smoke test, but they're often not good indicators that your program can handle the more extreme test cases too. You should always test with more than the sample inputs. If my calculations are correct, your program will produce the wrong result for the following input:
999000 999250
For reference, the expected output for this is:
999000 999250 321
There, I narrowed your search space down to 251 cycles :) Now get your debugger and finish the job.
Anyway, what follows is the full explanation and solution in spoiler markup. Mouse over the blank space if you want to read it, stay put if you want to figure it yourself.
The problem states that i and j are less than one million and that no operation overflows a 32-bit integer. This means that no intermediate result will be larger than 4294967295. However, an int is a signed type, so, even if it has 32-bits, it only has 31 bits for the absolute value, and thus cannot fit any number larger than 2147483647. Numbers larger than these occur in the cycles of for several Ns in the problem range, one of which is 999167. Using an unsigned 32 bit integer is one solution.
There is nothing mystery. The largest intermediate number overflows 31-bit of the signed integer. You need to declare record.number and nextNumber as unsigned int.