Endless loop when using unsigned int [duplicate] - c++

This question already has answers here:
Infinite loop when using size_t in a count down for loop
(6 answers)
Closed 2 years ago.
I have written a function that has to return n of bit "1" in binary representation. I have observed unexpected (for me) behavior.
When I'm using unsigned int type in a for loop, the function gets stuck in an endless loop, I have no idea why.
unsigned int countBits(unsigned long long n)
{
//your code here
int nofbits= log2(n)+1,
nofone=0;
for(int i=nofbits;i>=0;--i)
{
if(n-pow(2,i)>=0)
{
nofone++;
n=n-pow(2,i);
}
}
return nofone;
}
vs with endless loop
unsigned int countBits(unsigned long long n)
{
//your code here
int nofbits= log2(n)+1,
nofone=0;
for(unsigned i=nofbits;i>=0;--i)
{
if(n-pow(2,i)>=0)
{
nofone++;
n=n-pow(2,i);
}
}
return nofone;
}

As the name of the type indicates, an unsigned int can never become negative. Decrementing an unsigned int value 0 results in the maximum value an unsigned int can take on. Hence, a comparison like i >= 0 with i being of type unsigned int will always be true.

for(unsigned i=nofbits;i>=0;--i)
it will always be greater than 0 because it is unsigned. An unsigned number can only be >= 0.
From the comments, Remy Lebeau commented that when you subtract 1 from an unsigned 0, it will wrap around you end up with a very large number: 4294967295

Related

strange behavior of unsigned long long int in loop

While was solving this problem on hackerrank, I noticed a strange thing in the for loop. First, let me show an example code:
#include <bits/stdc++.h>
using namespace std;
#define modVal 1000000007;
int main() {
for(long long int i=2;i>=0;--i){
cout<<"here: "<<i<<endl;
}
}
input: 123
output: here: 2
here: 1
here: 0
164
Now, when I change long long int to unsigned long long int in for loop for the initialization of variable i. The variable i gets initialized with 18446744073709551615. Why is this happening?
When the variable is unsigned, i >= 0 is always true. So your loop never ends. When i gets to 0, the next -- makes i 0xFFFFFFFFFFFFFFFF (decimal 18446744073709551615).
Because unsigned types can't be negative, attempting to set them to a negative value will make them wrap around and instead hold std::numeric_limits<T>::max() - abs(value) + 1 where T is the type and value the value below 0.
In your loop once i reaches 0 the condition i >= 0 is still met and thus it would get decremented to -1 but that is impossible for unsigned types as explained above and thus the loop will never exit.
The unsigned numbers as the name suggests don't take signed values. So when i = -1 it is actually 0xFFFFFFFFFFFFFFFF(18446744073709551615 in decimal).
You can see that yourself with the modified program.
#include <bits/stdc++.h>
using namespace std;
#define modVal 1000000007;
int main() {
for(unsigned long long int i=2;i>=0;--i){
cout<<"here: "<<i<<endl;
if(i > 3)
return 0;
}
}

Determine if subtracting from an unsigned int will roll over [duplicate]

This question already has answers here:
Checking for underflow/overflow in C++?
(5 answers)
Saturating subtract/add for unsigned bytes
(11 answers)
Closed 3 years ago.
How can it be possible to determine if subtracting n from an unsigned int will roll over to a negative value, considering that casting to a signed int can result in a negative value already?
Example
#include <iostream>
using namespace std;
int main(){
unsigned int i = 2147483647*2;
if((int)i - 1 < 0){
cout << "rolled over";
}
else {
i = 0;
}
return 0;
}
In order to check if subtracting from an unsigned int would roll over, you could cast it to an int first. However, if the unsigned int is > the max int value, you will already end up negative. So how can I prevent an unsigned int from rolling over?

Unsigned int not working C++

Following are different programs/scenarios using unsigned int with respective outputs. I don't know why some of them are not working as intended.
Expected output: 2
Program 1:
int main()
{
int value = -2;
std::cout << (unsigned int)value;
return 0;
}
// OUTPUT: 4294967294
Program 2:
int main()
{
int value;
value = -2;
std::cout << (unsigned int)value;
return 0;
}
// OUTPUT: 4294967294
Program 3:
int main()
{
int value;
std::cin >> value; // 2
std::cout << (unsigned int)value;
return 0;
}
// OUTPUT: 2
Can someone explain why Program 1 and Program 2 don't work? Sorry, I'm new at coding.
You are expecting the cast from int to unsigned int to simply change the sign of a negative value while maintaining its magnitude. But that isn't how it works in C or C++. when it comes to overflow, unsigned integers follow modular arithmetic, meaning that assigning or initializing from negatives values such as -1 or -2 wraps around to the largest and second largest unsigned values, and so on. So, for example, these two are equivalent:
unsigned int n = -1;
unsigned int m = -2;
and
unsigned int n = std::numeric_limits<unsigned int>::max();
unsigned int m = std::numeric_limits<unsigned int>::max() - 1;
See this working example.
Also note that there is no substantial difference between programs 1 and 2. It is all down to the sign of the value used to initialize or assign to the unsigned integer.
Casting a value from signed to unsigned changes how the single bits of the value are interpreted. Lets have a look at a simple example with an 8 bit value like char and unsigned char.
The values of a character value range from -128 to 127. Including the 0 these are 256 (2^8) values. Usually the first bit indicates wether the value is negativ or positive. Therefore only the last 7 bits can be used to describe the actual value.
An unsigned character can't take any negative values because there is no bit to determine wether the value should be negative or positiv. Therfore its value ranges from 0 to 256.
When all bits are set (1111 1111) the unsigned character will have the value 256. However the simple character value will treat the first bit as an indicator for a negative value. Sticking to the two's complement this value will be -1.
This is the reason the cast from int to unsigned int does not what you expected it to do, but it does exactly what its supposed to do.
EDIT
If you just want to switch from negative to positive values write yourself a simple function like that
uint32_t makeUnsigned(int32_t toCast)
{
if (toCast < 0)
toCast *= -1;
return static_cast<uint32_t>(toCast);
}
This way you will convert your incoming int to an unsigned int with an maximal value of 2^32 - 1

How to implement N choose R?

I just wrote this code :
#include <iostream>
using namespace std;
unsigned long long int choose(unsigned long long int k, unsigned long long int n)
{
if (k==n or k==0)
{
return 1;
}
else
{
return (choose(n-1,k-1)+choose(n-1,k));
}
}
int main(){
cout << choose(3, 6);
}
but I got Run-Time Error, I think my problem is in my variables, I did debugging but I couldn't find the answer, why I got run time error?
Since your variables are unsigned, substracting 1 from them when they're already 0 will make them roll over to the max value.
When n reaches 0 and you then call choose(n-1,k), this'll happen and that's the source of the issue (stackoverflow).

Find largest unsigned int .... Why doesn't this work?

Couldn't you initialize an unsigned int and then increment it until it doesn't increment anymore? That's what I tried to do and I got a runtime error "Timeout." Any idea why this doesn't work? Any idea how to do it correctly?
#include
int main() {
unsigned int i(0), j(1);
while (i != j) {
++i;
++j;
}
std::cout << i;
return 0;
}
Unsigned arithmetic is defined as modulo 2^n in C++ (where n is
the number of bits). So when you increment the maximum value,
you get 0.
Because of this, the simplest way to get the maximum value is to
use -1:
unsigned int i = -1;
std::cout << i;
(If the compiler gives you a warning, and this bothers you, you
can use 0U - 1, or initialize with 0, and then decrement.)
Since i will never be equal to j, you have an infinite loop.
Additionally, this is a very inefficient method for determining the maximum value of an unsigned int. numeric_limits gives you the result without looping for 2^(16, 32, 64, or however many bits are in your unsigned int) iterations. If you didn't want to do that, you could write a much smaller loop:
unsigned int shifts = sizeof(unsigned int) * 8; // or CHAR_BITS
unsigned int maximum_value = 1;
for (int i = 1; i < shifts; ++i)
{
maximum_value <<= 1;
++maximum_value;
}
Or simply do
unsigned int maximum = (unsigned int)-1;
i will always be different than j, so you have entered an endless loop. If you want to take this approach, your code should look like this:
unsigned int i(0), j(1);
while (i < j) {
++i;
++j;
}
std::cout << i;
return 0;
Notice I changed it to while (i<j). Once j overflows i will be greater than j.
When an overflow happens, the value doesn't just stay at the highest, it wraps back abound to the lowest possible number.
i and j will be never equal to each other. When an unsigned integral value achieves its maximum adding to it 1 will result in that the next value will be the minimum that is 0.
For example if to consider unsigned char then its maximum is 255. After adding 1 you will get 0.
So your loop is infinite.
I assume you're trying to find the maximum limit that an unsigned integer can store (which is 65,535 in decimal). The reason that the program will time out is because when the int hits the maximum value it can store, it "Goes off the end." The next time j increments, it will be 65,535; i will be 0.
This means that the way you're going about it, i would NEVER equal j, and the loop would run indefinitely. If you changed it to what Damien has, you'd have i == 65,535; j equal to 0.
Couldn't you initialize an unsigned int and then increment it until it doesn't increment anymore?
No. Unsigned arithmetic is modular, so it wraps around to zero after the maximum value. You can carry on incrementing it forever, as your loop does.
Any idea how to do it correctly?
unsigned int max = -1; // or
unsigned int max = std::numeric_limits<unsigned int>::max();
or, if you want to use a loop to calculate it, change your condition to (j != 0) or (i < j) to stop when j wraps. Since i is one behind j, that will contain the maximum value. Note that this might not work for signed types - they give undefined behaviour when they overflow.