The rules for addition of binary numbers are straightforward:
Negative Numbers in the Computer
Another way to subtract, however, is by adding a
negative. Let's use subtraction via negatives
from decimal arithmetic as our guide. How do we subtract numbers in
base-10 notation?
So the key is to convert the number we're subtracting to its
negative!
For this purpose, we introduce "signed 8-bit integers". Since we are
limited to an 8-bit representation, we remain also limited to a total of
256 numbers. However, half of them will be negative (-128 through
-1) and half will be positive (0 through 128).
The representation of signed (positive and negative) numbers in the
computer is done through the so-called 8-bit 2's complement
representation. In this representation, the 8th bit indicates the sign
of the number (0 = +, 1 = -).
This 2's complement must conform to the regular laws of signed
arithmetic. Since 3 + (-3) = 0, the same cancellation
law must be verified when performing signed binary arithmetic. This
is assured when constructing the 2's complement negative binary
numbers through the following rule:
To find the negative of a number in 8-bit 2's complement
representation, simply subtract the number from zero, i.e. (-X) = 0 -
X using 8-bit binary arithmetic. That means that:
****************************************************************
For example, to represent (-3) in 8-bit 2's complement form:
Subtract the 8-bit binary representation of 3 from the
8-bit binary representation of 0 using 8-bit arithmetic (8-bit
arithmetic implies that you can liberally take from, or carry into the
9th bit, since only the first 8 bits count... the 9th bit is
irrelevant since it's not stored!).
Now let's verify that 3 + (-3) = 0 using the 8-bit
arithmetic.
2's complement explanation
Arithmetic Operations
In the same way, we can do subtractions:
0 + 0 = 0, 0 + 1 = 1, and 1 + 1 = 0 with a carry of 1, i.e. 1 + 1 =
10
Notice, in this example, if we're representing 1-bit digits, we
borrowed a 1 from the 2nd bit. But, since our representation is
1-bit, that 2nd bit becomes irrelevant!
0 - 0 = 0, and 1 - 1 = 0, and 0 - 1 = 1 with a carry of 1 (i.e., 0 - 1
= 10 - 1 = 01)
3 - 3 = 3 + (-3) = 0
2's complement is simply subtracting the number from 0 (e.g., in an
8-bit representation)
****************************************************************
Note that, in this operation, a 1 was liberally borrowed from the 9th
bit and used in the subtraction! Thus, we have established that (-3)
in base 2 is 11111101.
DECIMAL: 0
- 3
= (-3)
BINARY: 00000000
- 00000011
= (11111101)
Note that, in this operation, a carry of 1 was liberally lost in the
9th bit! Since the 9th bit is irrelevant, the answer is actually
00000000, as expected. The rule outlined above can be applied to both
binary and hex numbers.
DECIMAL: 3 + (-3) = 0
BINARY: 00000011 + (11111101) = 00000000
****************************************************************
Why use 2's complements at all? Simply because keeping track
of a signed bit and adding or subtracting based on that is cumbersome
and requires a lot of processing. On the other hand, representing a
negative number with its 2's complement and adding that to another
number is much easier and much less processor-intensive. Also, see
here (http://www.cs.utk.edu/~eijkhout/pic3/ref_machine.html)
which
points out that without 2's complement, you have 2 zero's, both 0 and -0
(also note that adding one to the bit pattern of a negative number
(i.e., incrementing its bit pattern by one, without 2's complement)
would actually subtract one from that number, not add one to it).
****************************************************************
Passing parameters by value, pointer, or reference:
fn(int vInt)
fn(int *pInt)
A reference variable is an "alias"; its value changes when
its assigned variable changes and vice versa (i.e., a
reference is simply another name for the variable):
fn(int &rInt)
void foo(int x); // pass by value
void foo(int* x); // pass using pointer
void foo(int& x); // pass by reference
// Pass by value:
int main() {
int y = 23;
foo(y);
// y has not changed.
return 0;
}
void foo(int x) {
x = 13;
}
// Pass by pointer:
int main() {
int y = 23;
foo(&y);
// y has changed to 13
return 0;
}
void foo(int* x) {
*x = 13;
}
// Pass by reference:
int main() {
int y = 23;
foo(y);
// y has changed to 13
return 0;
}
void foo(int& x) {
x = 13;
}
References:
Ricky J. Sethi <rickys at sethi.org>
Last modified: Thu Jul 24 18:17:56 PDT 2003