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;
}
}
Related
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
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
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).
I am trying to manipulate 64 bits. I use the number to store in an unsigned long long int.To test the porcess I ran the following program
#include <iostream>
using namespace std;
int main()
{
unsigned long long x = 1;
int cnt = 0;
for(int i =0 ;i<64;++i)
{
if((1<<i)&x)
++cnt;
}
cout<<cnt;
}
but the output of the cnt is 2 which is clearly wrong. How Do I manipulate 64 bits? where is the correction? Actually I am trying to find parity, that is number of 1's in binary representation of a number less than 2^63.
For it's 64-bit, you should use a 64-bit 1. So, try this:
if(((unsigned long long) 1<<i)&x)
(1<<i) will overflow when i greater than 32
you can write the condition like (x >> i) & 1
What is meant by manipulation in your case? I am thinking you are going to test each and every bit of variable x. Your x should contain maximum value because you are going to test every bit of your variable x
int main()
{
unsigned long long x = 0xFFFFFFFFFFFFFFFF;
int cnt = 0;
for(int i =0 ;i<64;++i)
{
if((1<<i)&x)
++cnt;
}
cout<<cnt;
}
So basically, I have something like this -
Input file with 2 integers.
Code, something like this -
#include <iostream>
#include <fstream>
using namespace std;
int main() {
unsigned long long n, k;
ifstream input_file("file.txt");
input_file >> n >> k;
if(n >= 10^9 || k >= 10^9) {
cout << "0" << endl;
}
return 0;
}
So, is there any chance to check if any of theese two integers are bigger than 10^9? Basically, if I assign thoose integers to unsigned long long, and if they are bigger than 10^9, they automatically turn to some random value, that fits inside unsigned long long, am I right, and that means that there is no chance to check it, or am I'm missing something?
I'm bad at counting zeroes. That's the machine's job. What about 1e9 instead of a bit operation 10^9.
On most platforms, an unsigned long long will be able to store 109 with no problem. You just need to say:
if (n >= 1000000000ull)
If an unsigned long long is 64-bits, for example, which is common, you can store up to 264
Read into a string:
std::string s;
input_file >> s;
and check if it's longer than 9 characters. If it's exactly 9, see that it's not exactly "1000000000" (1 and eight 0's).
For 10^9 you need to write 1000000000LL. In C++ ^ is the bitwise XOR operator, not exponentiaion. You also need the LL to ensure that the literal constant is interpreted as long long rather than just int.
if (n >= 1000000000LL || k >= 1000000000LL)
{
...
}
Of course if the user enters a value which is too large to be represented by a long long (greater than 2^63-1, typically) then you have a bigger problem.