How do these two conditions differ? [duplicate] - c++

This question already has answers here:
Casting int to bool in C/C++
(3 answers)
Closed 2 years ago.
I was wondering if you could clarify me the difference between the conditions while(k) and while(k > 0) when do they differ?
#include <iostream>
int main() {
int k;
std::cin >> k;
while(k) {
std::cout << "Hello" << "\n";
k--;
}
}
#include <iostream>
int main() {
int k;
std::cin >> k;
while(k > 0) {
std::cout << "Hello" << "\n";
k--;
}
}

The two code snippets you present will give equivalent results if – and only if – the input value for k is not negative. Try it.
Specifically, for the first snippet, if a value of -1 is input for k, the --k; line inside the while loop will (maybe) never reduce k to zero, or (maybe) just take a long time (until k reaches INT_MIN – something like -2147483648), depending on how the platform you are using handles signed integer underflow.
The while (k) loop will run until k is zero.
However, in the second snippet, a negative input for k will mean that the loop never runs (k will not be greater than zero on the first test).

Related

Fraction pattern in c++ [duplicate]

This question already has answers here:
C++. Dividing 1 by any number gives 0
(3 answers)
Closed 1 year ago.
I need to write a program to run this pattern in c++:
S=1/2+2/3+3/4+4/5+...+N-1/N
I have tried but my code is showing 0.
And its the code that I have written:
#include <iostream>
using namespace std;
int main()
{
unsigned int N;
float S=0;
cout << "Enter N:";
cin >> N;
for (int I = 2; I <= N; I++)
{
S = S + (I - 1) / I;
}
cout << S;
return 0;
}
I have to write it with for-loop, while and do-while
(I - 1) / I only contains integers, therefore any remainder is discarded.
You can avoid this by simply subtracting - 1.f off of I instead.

Getting negative outputs for large enough inputs in vector

I was writing an algorithm for a problem that goes as follows:
Consider an algorithm that takes as input a positive integer n. If n is even, the algorithm divides it by two, and if n is odd, the algorithm multiplies it by three and adds one. The algorithm repeats this until n is one. For example, the sequence for n=3 is as follows:
3→10→5→16→8→4→2→1
Original question can be found here
The algorithm that I wrote for it is as follows:
#include <iostream>
#include<vector>
using namespace std;
void check(long int n, vector<int> &arr);
int main(){
long int n;
cin>>n;
vector<int> arr; //Vector to store values of n
check(n,arr);
for(unsigned int i=0;i<arr.size();i++){
cout<<arr[i]<<' '; //Printing the final values of n
}
return 0;
}
void check(long int n,vector<int> &arr){
arr.push_back(n);
if(n%2==0){ //if n is even
n=n/2;
if(n!=1){
check(n,arr);
}
else if(n==1){
arr.push_back(1);
}
}
else{ //if n is odd
n=(n*3)+1;
if(n!=1){
check(n,arr);
}
else if(n==1){
arr.push_back(1);
}
}
return;
}
My solution is working perfectly for smaller values of n. However when n becomes large enough- especially somewhere around 138367(this was the first test case when the answer got wrong according to the compiler), the values of n printed at the end also start to include some 'negative numbers', which is somewhat unreasonable.
For instance, if I input n=986089625, in the beginning, the next number that follows it in the end result is -1336698420. While the correct number should be 2958268876. Surprisingly the next number that follows is correct, but at certain (random) intervals, the numbers are becoming negative.
I know the algorithm can be simplified further, but I'm not able to understand the problem with this one. I assume there's something subtle that I'm missing!
You can see how this works with this simple example
#include <limits.h>
#include <iostream>
int main()
{
int n = INT_MAX;
std::cout << "n=" << n << '\n';
std::cout << "n+1=" << n + 1 << '\n';
unsigned m = UINT_MAX;
std::cout << "m=" << m << '\n';
std::cout << "m+1=" << m + 1 << '\n';
}
giving
n=2147483647
n+1=-2147483648
m=4294967295
m+1=0
When the limit is reached, a wrap around occurs to either INT_MIN or zero, depending on the signedness of the integer type.
The same happens also in the opposite direction of course, wrapping from INT_MIN to INT_MAX or from zero to UINT_MAX.
Typical int (signed 32-bit long) can store numbers only upto 2,147,483,647 (2**31 - 1) and the number 2958268876 exceeds this limit.
You are using long int for calculation, so you should use it also for the elements of vector.
In other words, the three vector<int>s should be replaced with vector<long int>.

C++ - Digitwise addition with carryover for arbitrary unsigned ints - running into memory problems [duplicate]

I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<double> x(10);
for (unsigned int i = 9; i >= 0; i--)
{
cout << "i= " << i << endl;
x[i] = 1.0;
}
cout << "x0= " << x[0] << endl;
return 0;
}
I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
Thank you very much!
The problem here is that an unsigned integer is never negative.
Therefore, the loop-test:
i >= 0
will always be true. Thus you get an infinite loop.
When it drops below zero, it wraps around to the largest value unsigned value.
Thus, you will also be accessing x[i] out-of-bounds.
This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.
Thus, if you want to use unsigned integers, you can try one of the following possibilities:
for (unsigned int i = 9; i-- != 0; )
and
for (unsigned int i = 9; i != -1; i--)
These two were suggested by GManNickG and AndreyT from the comments.
And here's my original 3 versions:
for (unsigned int i = 9; i != (unsigned)0 - 1; i--)
or
for (unsigned int i = 9; i != ~(unsigned)0; i--)
or
for (unsigned int i = 9; i != UINT_MAX; i--)
The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.
Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.
In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).
The problem is here:
for (unsigned int i = 9; i >= 0; i--)
You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).
As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
My preferred method for a reverse loop with an index is this:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
and that is why because it maps most closely to the normal loop equivalent:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}
If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:
auto& my_element = my_vector[i - 1];

C++ program doesn't fully execute iteration [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 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.

Unsigned integers in C++ for loops

I have made some research on Stackoverflow about reverse for loops in C++ that use an unsigned integer instead of a signed one. But I still do NOT understand why there is a problem (see Unsigned int reverse iteration with for loops). Why the following code will yield a segmentation fault?
#include <vector>
#include <iostream>
using namespace std;
int main(void)
{
vector<double> x(10);
for (unsigned int i = 9; i >= 0; i--)
{
cout << "i= " << i << endl;
x[i] = 1.0;
}
cout << "x0= " << x[0] << endl;
return 0;
}
I understand that the problem is when the index i will be equal to zero, because there is something like an overflow. But I think an unsigned integer is allowed to take the zero value, isn't it? Now if I replace it with a signed integer, there is absolutely no problem.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
Thank you very much!
The problem here is that an unsigned integer is never negative.
Therefore, the loop-test:
i >= 0
will always be true. Thus you get an infinite loop.
When it drops below zero, it wraps around to the largest value unsigned value.
Thus, you will also be accessing x[i] out-of-bounds.
This is not a problem for signed integers because it will simply go negative and thus fail i >= 0.
Thus, if you want to use unsigned integers, you can try one of the following possibilities:
for (unsigned int i = 9; i-- != 0; )
and
for (unsigned int i = 9; i != -1; i--)
These two were suggested by GManNickG and AndreyT from the comments.
And here's my original 3 versions:
for (unsigned int i = 9; i != (unsigned)0 - 1; i--)
or
for (unsigned int i = 9; i != ~(unsigned)0; i--)
or
for (unsigned int i = 9; i != UINT_MAX; i--)
The problem is, your loop allows i to be as low as zero and only expects to exit the loop if i is less than 0. Since i is unsigned, it can never be less than 0. It rolls over to 2^32-1. That is greater than the size of your vector and so results in a segfault.
Whatever the value of unsigned int i it is always true that i >= 0 so your for loop never ends.
In other words, if at some point i is 0 and you decrement it, it still stays non-negative, because it contains then a huge number, probably 4294967295 (that is 232-1).
The problem is here:
for (unsigned int i = 9; i >= 0; i--)
You are starting with a value of 9 for an unsigned int and your exit definition is i >= 0 and this will be always true. (unsigned int will never be negative!!!). Because of this your loop will start over (endless loop, because i=0 then -1 goes max uint).
As you said a decrease of an unsigned below zero, which happens right after the last step of the loop, creates an overflow, the number wraps around to its maximum value and thus we end up with an infinite loop.
Does somebody can explain me the mechanism behind that reverse loop with an unsigned integer?
My preferred method for a reverse loop with an index is this:
for (unsigned int i = 9; i > 0; --i) {
cout << "i= " << x[i - 1] << endl;
}
and that is why because it maps most closely to the normal loop equivalent:
for (unsigned int i = 0; i < 9; ++i) {
cout << "i= " << x[i] << endl;
}
If then you need to access the indexed element multiple times and you don't want to continuously write [i - 1], you can add something like this as the first line in the loop:
auto& my_element = my_vector[i - 1];