Reputation: 41
I'm new here so really sorry if this is to basic but what am I missing here? This is just a dummy code:
#include <iostream>
using namespace std;
int main() {
unsigned int a, b, c;
int d;
a = 10E06;
b = 25E06;
c = 4096;
d = (a - b)/c;
std::cout << d << std::endl;
return 0;
}
cout is printing 1044913 instead of -3662. If I cast a and b to long the problem is solved. Is there a problem of overflow or something?
Upvotes: 1
Views: 282
Reputation: 1147
Because of the way C++ (and many other C-based languages) deal with operators, when unsigned numbers are put into an expression, that expression returns an unsigned value, and not held in a mysterious inter-type state that might be expected.
Step-by-step:
(a - b)
subtracts 25E06 from 10E06, which would normally return -15E06, is unsigned, so it's wrapped around to a whole bunch of junk."unsigned int" is a type just like float and bool, even though it requires two keywords. If you want it to turn into a signed int for that calculation, you must either make sure a, b, and c are all signed (remove the unsigned keyword), or cast them as such when putting them into the expression, like this: d = ((signed)a - (signed)b) / (signed)c;
Upvotes: 1
Reputation: 283
You want your result to take a sign. So you should declare your variables as signed int or just int. That will give the desired result. If you cast a and b to long, a-b will be long and hence take a sign. Following is a solution.
int main() {
int a, b, c;
int d;
a = 10E06;
b = 25E06;
c = 4096;
d = (a - b)/c;
std::cout << d << std::endl;
return 0;
}
If you also want rational numbers you should use doubles or float (atlhough it won't give a different result for this particular case).
int main() {
double a, b, c;
double d;
a = 10E06;
b = 25E06;
c = 4096;
d = (a - b)/c;
std::cout << d << std::endl;
return 0;
}
Upvotes: 1
Reputation: 22406
Since a b and c are all declared as unsigned, the output of the computation (a-b)/c will be unsigned. Since the calculation of the values you provided cannot be properly represented with an unsigned type, things get a little messy. The unsigned value is then assigned to d, and even though this is signed, the value is already garbled.
I will also note that the notation 10E06 represents a floating point number that is then being implicitly cast to an unsigned int. Depending on the particular floating point value provided, this may or may not cast as expected.
Upvotes: 2
Reputation: 258548
Operations between unsigned numbers yield unsigned numbers. It's up to you to make sure the operations make sense, or protect against the opposite.
If you have unsigned int a = 2, b = 3;
, what do you think the value of a-b
would be?
Upvotes: 3
Reputation: 20766
That's because (a-b)
itself is unsigned:
#include <iostream>
using namespace std;
int main() {
unsigned int a, b, c;
int d;
a = 10E06;
b = 25E06;
c = 4096;
d = (a - b)/c;
std::cout << (a-b) << std::endl; // 4279967296
std::cout << d << std::endl; // 1044913
return 0;
}
The conversion from unsigned
to int
happens when d
is assigned to, not before.
So (a-b)/c
must be unsigned since a,b,c
are.
Upvotes: 4