user3192199
user3192199

Reputation: 41

Division of integers in C++ not working as expected

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

Answers (5)

einsteinsci
einsteinsci

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.
  • This junk is then divided by c, and both inputs are unsigned, so the output is also unsigned.
  • Lastly, this is stuffed into a signed int, remaining at 1044913.

"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

user3116431
user3116431

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

csj
csj

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

Luchian Grigore
Luchian Grigore

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

Matt
Matt

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

Related Questions