Unsigned Integer Binary Subtraction

6.3k Views Asked by At

So I am having a bit of an issue. First, what is the difference between doing an unsigned binary integer subtraction and doing a signed integer subtraction? I think that is what is confusing me. For an unsigned integer, I was told that you have to add a 0 next to the most significant bit (I may be wrong), but I don't feel comfortable with that. After watching a couple of videos on youtube, I tried to the subtraction.

0011 0001 – 1010 1011

My thought process: I decided to take 1010 1011 and do one's complement and then two's complement and then add it to 0011 0001.

Click here to see my work

2

There are 2 best solutions below

4
On

In unsigned binary, all numbers are positive and you can't subtract a larger one from a smaller one. If we translate your problem to base $10$ we get $49-171$ which does not have an answer. For unsigned binary you just do subtraction like you learned in school except in base $2$, borrowing when necessary. So if we want to do your problem in reverse, $171-49$ we get $$\begin {align}1010 1011&\\ \underline {-0011 0001}& \\01111010& \end {align}$$ where we borrowed in the $2^5$ place and it carried to the next two.

0
On

This is a reasonable answer from a mathematical point of view, but not a great answer from computer science point of view. To understand this you want to look at the most common two's complement binary math https://notesformsc.org/2s-complement-subtraction/. This also overlaps an interesting subject in math, modular arithmetic (since register sizes are fixed) used to prevent rollover issues when doing timing math see http://www.gammon.com.au/forum/?id=12127.

The C++ program below shows that if you interpret the number as time subtracting T2-T1 works even if the counter has rolled over (gone from large to small) once. It also shows that if you allow promotion to large types you get, what may be initially, unexpected values.

#include <iostream>
#include <cmath>
#include <bitset>


void take_short_diff(unsigned short T1, unsigned short T2)
{
    //Force all math to happen without promotion
    unsigned char diff = (unsigned char)(T2 - T1);
    //Ints below are just so it doesn't print as characters, they don't impact the problem
    std::cout << "\n\nT1  =" << (int)T1 << "\nT2  =" << (int)T2 << "\ndiff=" << (int)diff;
    //Show the binary pattern
    std::cout << "\nT1  =" << std::bitset<8>(T1) << "\nT2  =" << std::bitset<8>(T2) << "\ndiff=" << std::bitset<8>(diff);
    //Allow promotion to short
    short diff_short = T2 - T1;
    std::cout << "\ndiff short=" << diff_short;
    std::cout << "\n" << std::bitset<16>(diff_short);
    //Allow promotion to unsigned short
    unsigned short diff_short_u = T2 - T1;
    std::cout << "\ndiff short unsigned=" << diff_short_u;
    std::cout << "\n" << std::bitset<16>(diff_short_u);
}

void main()
{
    take_short_diff(0, 2);
    take_short_diff(253, 255);
    take_short_diff(254, 1);
}