tedj@hpcilzb.HP.COM (Ted Johnson) (01/25/88)
Could someone please explain why the following statements both give the same answer? short int x, y = 12; x = -y -1; vs. short int x, y = 12; x = ~y; Both ways end up assigning x the value of -13. K&R say something about the ~ operator taking the one's complement of a number, but I didn't follow their explanation... The only reason I ask is because I saw two different programs compute the same function in two different ways, and I want to know if they are really doing the same thing or if this is a special case where both functions give the same answer. Thanks in advance! -Ted P.S. This was on a machine where a short int is 16 bits.
boemker@hpfcdc.HP.COM (Tim Boemker) (01/27/88)
> Could someone please explain why the following statements both give the > same answer? x= -y -1; vs. x = ~y; On most computers, integers are stored in two's complement form. For a positive integer, that's the normal representation. For a negative integer, the two's complement is the one's complement plus one. (Adding one may seem curious, but it has an important advantage: there's only one representation for zero. In a one'c complement scheme, both a word of 1's and a word of 0's represent zero.) Let y be a positive integer. -y = ~y + 1 by definition of two's complement -y - 1 = ~y QED.
scjones@sdrc.UUCP (Larry Jones) (01/27/88)
In article <1620006@hpcilzb.HP.COM>, tedj@hpcilzb.HP.COM (Ted Johnson) writes: > > Could someone please explain why the following statements both give the > same answer? > > x = -y -1; > x = ~y; Congratuations! You've just discovered "two's complement". This is the system that most current computers use for representing integer values. To fully understand it, you need to first understand "one's complement". In the one's complement, the negative of a number is represented by negating each bit of the number. For example, if you have the number 12 (00001100) then -12 is (11110011). This is called one's complement since adding a number to its negative results in a one in each bit position. This is what the ~ operator does, it complements each bit in a number. Although one's complement is a simple and easily understandable system, it has a number of disadvantages, not the least of which is that +0 and -0 each have representations. Since most people expect to have a single representation for zero, two's complement has become more popular. Two's complement is just like one's complement except that after you complement each bit, you add one to the result. Thus in two's complement notation -12 is (11110100). So, on a two's complement machine, -y == ~y + 1 which can be rearranged into the identity you discovered ~y == -y - 1. Please note, however, that this is NOT portable since there are still a few machines that use one's complement arithmetic rather than two's complement. -- ---- Larry Jones UUCP: uunet!sdrc!scjones SDRC MAIL: 2000 Eastman Dr., Milford, OH 45150 AT&T: (513) 576-2070 "When all else fails, read the directions."
tedj@hpcilzb.HP.COM (Ted Johnson) (01/28/88)
Thanks for the info., I get it now! (I am posting this so that people will stop e-mailing me explanations!) -Ted
bright@Data-IO.COM (Walter Bright) (01/28/88)
In article <1620006@hpcilzb.HP.COM> tedj@hpcilzb.HP.COM (Ted Johnson) writes:
<Could someone please explain why the following statements both give the
<same answer?
< x = -y -1; vs. x = ~y;
For a two's complement machine, the following identity is true:
-y == ~y + 1
This property is frequently exploited in assembly language programs.
jrl@anuck.UUCP (j.r.lupien) (01/28/88)
In article <1620006@hpcilzb.HP.COM>, tedj@hpcilzb.HP.COM (Ted Johnson) writes: > Could someone please explain why the following statements both give the > same answer? > short int x, y = 12; > x = -y -1; > vs. > short int x, y = 12; > x = ~y; > > Both ways end up assigning x the value of -13. > P.S. This was on a machine where a short int is 16 bits. Ones complement means "change the state of each bit in the word", 1's => 0, 0's => 1. Most C implementations use "twos complement" for negative integers. This means that, for your machine, a -1 is represented as: 0xFFFF or b1111111111111111 So, if we do -1 -y, you have b1111111111111111 - b0000000000001100 -------------------- b1111111111110011 which happens to be the one's complement. As you can see, whatever pattern of bits appears as the diminuend in this subtraction is going to be inverted. If y is negative, you should still get the inverted bit pattern, but you may get an overflow. Actually, this is a somewhat simple way to look at things, in that it only answers the question that was asked, and fails to appropriately expand on the implementation issues that arise. For instance, the "subtract" operation may exist as an opcode on the machine, or it may not. If not, it is implemented as a special form of "add the twos complement of the diminuend", a sort of "to subtract, add the negative" implementation. To get back to the question, I use ~ for bitwise inversion. It is probably best to stick with bitwise operators for bitwise operations and arithmetic operators for arithmetic operations. This way, the vagaries of implementation are sidestepped. Implementors are responsible for assuring that these operations work correctly, whereas "tricks" have to be tested anew each time you port. John R. Lupien ihnp4!mvuxa!anuxh!jrl
nevin1@ihlpf.ATT.COM (00704a-Liber) (01/28/88)
In article <1620006@hpcilzb.HP.COM> tedj@hpcilzb.HP.COM (Ted Johnson) writes:
.
.Could someone please explain why the following statements both give the
.same answer?
.
. short int x, y = 12;
.
. x = -y -1;
.vs.
.
. short int x, y = 12;
.
. x = ~y;
.
.
.Both ways end up assigning x the value of -13. K&R say something about
.the ~ operator taking the one's complement of a number, but I didn't
.follow their explanation...
.
.P.S. This was on a machine where a short int is 16 bits.
This is because you are working on a 2's complement machine.
To take the negative of a 2's complement number, you
invert all the bits (ie, take the 1's complement of the number which is
using '~'), then you add 1 to the result.
Therefore, on a 2's complement machine, ~y +1 === -y or, as you stated,
~y === -y - 1.
This is a machine dependent feature and is NOT guaranteed to be consistent
under all implementations of C.
--
_ __ NEVIN J. LIBER ..!ihnp4!ihlpf!nevin1 (312) 510-6194
' ) ) "The secret compartment of my ring I fill
/ / _ , __o ____ with an Underdog super-energy pill."
/ (_</_\/ <__/ / <_ These are solely MY opinions, not AT&T's, blah blah blah
dag@chinet.UUCP (Daniel A. Glasser) (01/28/88)
In article <1620006@hpcilzb.HP.COM> tedj@hpcilzb.HP.COM (Ted Johnson) writes: > >Could someone please explain why the following statements both give the >same answer? > short int x, y = 12; > x = -y -1; >vs. > short int x, y = 12; > x = ~y; >Both ways end up assigning x the value of -13. K&R say something about >the ~ operator taking the one's complement of a number, but I didn't >follow their explanation... in two's complement arithmetic, the additive inverse (negative) of a number is computed by taking the 1's complement (all 1's become 0's, 0's become 1's) of the bit pattern and adding 1. An example of this is: Decimal Binary 1 0000000000000001 start with the number -2 1111111111111110 take one's complement -1 1111111111111111 add 1 So, -x is the two's complement, ~x is the one's complement. -x - 1 is the one's complement, ~x + 1 is the two's complement. Does any of this make sense? (CS -101) -- Daniel A. Glasser ...!ihnp4!chinet!dag ...!ihnp4!mwc!dag ...!ihnp4!mwc!gorgon!dag One of those things that goes "BUMP!!! (ouch!)" in the night.
decot@hpisod2.HP.COM (Dave Decot) (01/29/88)
The most important advantage of two's complement (why do they call it that?) is that adding and subtracting integers is easier (you just add normally), and this makes hardware to build: 111010 (-6) + 001001 ( 9) -------------- 000011 ( 3) Dave Decot hpda!decot
amos@taux01.UUCP (Amos Shapir) (01/29/88)
Since no one had mentioned this yet, I guess I'll have to: In article <2148@chinet.UUCP> dag@chinet.UUCP (Daniel A. Glasser) writes: >in two's complement arithmetic, the additive inverse (negative) of >a number is computed by taking the 1's complement (all 1's become 0's, >0's become 1's) of the bit pattern and adding 1. The definition of 2's complement is actually a little different: the binary represantation of a negative value is obtained by adding to it 2**n (** means power), where n is the number of bits, and doing a 'pure' unsigned binary represantation of the result. E.g. to represent -2 in a 16-bit word: -2 + 65536 = 65534 = 0b1111111111111110 -- Amos Shapir (My other cpu is a NS32532) National Semiconductor (Israel) 6 Maskit st. P.O.B. 3007, Herzlia 46104, Israel Tel. +972 52 522261 amos%taux01@nsc.com 34 48 E / 32 10 N
tainter@ihlpg.ATT.COM (Tainter) (01/30/88)
In article <2550041@hpisod2.HP.COM>, decot@hpisod2.HP.COM (Dave Decot) writes: > > Could someone please explain why the following statements both give the > > same answer? > > short int x, y = 12; > > x = -y -1; > > x = ~y; > The one's complement means flip all bits. (~ x) > The two's complement means flip all bits and add one. (- x) In fact, given the definitions it should be obvious that (~x) == (-x - 1) A derivation for those having long since seen their intro algebra classes :-) (-x - 1) :=: ((~x+1) - 1) (-x - 1) :=: (~x + (1 - 1)) (-x - 1) :=: (~x) > Dave Decot --j.a.tainter