Integer Representation Representation of integers: unsigned and signed Sign extension Arithmetic and shifting Casting But first, encode deck of cards. cards in suits How do we encode suits, face cards? What operations should be easy to implement? Get and compare rank Get and compare suit Two possible representations cards bits with bit corresponding to card set to bits in x - bit words One- hot encoding Two - bit words Hard to compare values and suits Large number of bits required Two better representations Binary encoding of all cards only bits needed Number each card Fits in one byte low- order bits of a byte Smaller than one- hot encodings. How can we make value and suit comparisons easier? Binary encoding of suit ( bits) and value ( bits) separately bits for suit, bits for card value bits with two set to Pair of one- hot encoded values Fits in one - bit word Easier to compare suits and values Still space- inefficient Number each suit Number each value Fits in one byte Easy suit, value comparisons suit value
Compare Card Suits mask: a bit vector that, when bitwise ANDed with another bit vector v, turns all but the bits of interest in v to Compare Card Values mask: a bit vector that, when bitwise ANDed with another bit vector v, turns all but the bits of interest in v to static final SUIT_MASK = x; boolean samesuit(char card, char card) { return == ((card & SUIT_MASK) ^ (card & SUIT_MASK)); // return (card & SUIT_MASK) == (card & SUIT_MASK); } SUIT_MASK = x = suit value equivalent static final VALUE_MASK = xf; works even if value is stored in high bits boolean greatervalue(char card, char card) { return (card & VALUE_MASK) > (card & VALUE_MASK)); } VALUE_MASK = xf = suit value char hand[]; // represents a -card hand char card, card; // two cards to compare card = hand[]; card = hand[];... if ( samesuit(card, card) ) {... } char hand[]; // represents a -card hand char card, card; // two cards to compare card = hand[]; card = hand[];... if ( greatervalue(card, card) ) {... } Encoding Integers in a fixed number of bits Two flavors: unsigned ( ) non- negatives only Positional representation, fixed # of positions. signed ( ) both negatives and non- negatives fixed- width representations: W bits wide (W for word or width)??? Only W distinct bit patterns... Cannot represent all the integers Unsigned values:... W - Signed values: - W-... W- - Terminology: Unsigned modular arithmetic, overflow Examples in - bit unsigned representation. + = 8 + = Most- significant or high- order bit(s) Least- significant or low- order bit(s) x + y in N- bit unsigned arithmetic is (x + y) mod N in math MSB LSB unsigned overflow = "wrong" answer = wrap- around = carry out of MSB = math answer too big to fit
Overflow: Unsigned Addition overflows + if and only if a carry bit is dropped. + Overflow. 8 Signed Integers: Sign- Magnitude? Most- significant bit (MSB) is sign bit means non- negative means negative Rest of bits are an unsigned magnitude 8- bit sign- and- magnitude: x = represents xf = represents x8 = represents x8 = represents Max and min for N- bit sign- magnitude? Modular Arithmetic What is weird about sign- magnitude representation? Sign- Magnitude Negatives Another problem: cumbersome arithmetic. Example: -!= + (- ) + What about zero? Maybe sign- magnitude is not such a good idea... + + + + + + + Two s complement representation for signed integers w- bit representation _ _ - (w- ) i weight w- i position Positional representation, but most significant position has negative weight.
8- bit representations - bit unsigned vs. - bit two s complement x + x + x + x x - + x + x + x (math) difference = = - + + 8 8 + + + 8 + Two s complement: addition Just Works - + + - + - - + - - + + + + + + + 8 + Modular Arithmetic Overflow: Two s Complement Addition overflows - + - if and only if the inputs have the same sign but the output does not. if and only if the carry in and out of the sign bit differ. + No overflow. + Overflow. 8 + + + + + + Modular Arithmetic Some CPUs raise exceptions on overflow C and Java cruise along silently... Oops?
A few reasons two s complement is awesome Another view Better be true! x + -x == N- bit negative one is N ones. Complement rules: x + ~x == - ~x + == -x Duh! Very useful! How should we represent 8- bit negatives? For all positive integers x and widths n, the n- bit representations of x and x must sum to zero. Arithmetic should be the same. + + + Find a rule to represent x where that works Subtraction is just addition: - == + (- ) Great news for hardware. Conversion Visualized Values To Remember Two s Complement Unsigned Ordering Inversion Negative Big Positive s Complement Range TMax TMin UMax UMax TMax + TMax Unsigned Range Unsigned Values UMin = UMax = w Values for W = Two s Complement Values TMin = w TMax = w Negative one xf...f Decimal Hex Binary UMax,,, FF FF FF FF TMax,,8, F FF FF FF TMin -,,8,8 8 - - FF FF FF FF 8
Sign Extension Sign Extension Fill new bits with copies of the sign bit. 8- bit 8- bit - bit - bit 8- bit - 8- bit -???????? - bit - - bit - Try some possibilities Casting from smaller to larger signed type does sign extension. Shift Operations Shift gotchas Left shift: x << y Shift bit vector x left by y positions Throw away extra bits on left Fill with s on right Right shift: x >> y Shift bit vector x right by y positions Throw away extra bits on right Fill with??? on left Logical shift Fill with s on left Arithmetic shift Replicate most significant bit on left Why is this useful? Rain check! Argument x x << Logical: x >> Arithmetic: x >> Argument x x << Logical: x >> Arithmetic: x >> For a type represented by n bits, shift by no more than n-. C: shift by < or >(bits in type) is undefined. means anything could happen, including computer catching fire Java: shift value is used modulo number of bits in shifted type given int x: x << == x << in C: meaning of >> on signed types is compiler- defined! GCC: arithmetic shift in Java: >> is arithmetic, >>> is logical
Using Shifts and Masks Shifting and Arithmetic: unsigned Extract nd most significant byte from a - bit integer: unsigned x = ; x* n mod w x y = x << ; y == 8 logical shift left: shift in zeros from the right Extract the sign bit of a signed integer: x/ n unsigned x = ; logical shift right: shift in zeros from the left y = x >> ; y == Shifting and Arithmetic: signed Multiplication signed x = - ; x* n mod w Operands: w bits u y = x << ; y == 8 logical shift left: shift in zeros from the right True Product: *w bits Discard w bits: w bits u v * v unsigned: u * v = (u v) mod w For x > : x/ n signed x = - ; overflow iff any bit b y >= w!= signed: overflow iff any bit b y >= w!= b w- arithmetic shift right: shift in copies of MSB from the left y = x >> ; y == - Most programming languages For x < it rounds the opposite direction! More generally true about loss of value when casting to smaller types. High bits are just discarded. 8
Power- of- Multiply with Shift Operation u << k = u * k Both signed and unsigned Operands: w bits True Product: w+k bits u k Discard k bits: w bits UMult w (u, k ) TMult w (u, k ) Examples u << == u * 8 (u << ) - (u << ) == u * * u k k Signed vs. Unsigned in C Constants By default are considered to be signed integers Use U suffix to force unsigned: U, U Signed vs. Unsigned in C Casting: bits unchanged, just interpreted differently. int tx, ty; unsigned ux, uy; Explicit casting: tx = (int) ux; uy = (unsigned) ty; Implicit casting via assignments and function calls: tx = ux; uy = ty; gcc flag - Wsign- conversion warns about implicit casts; - Wall does not! C Casting Surprises Expression Evaluation If you mix unsigned and signed in a single expression, then signed values are implicitly cast to unsigned. Including comparison operations <, >, ==, <=, >= Examples for W = : TMIN = -,,8,8 TMAX =,,8, Constant Constant Relation Evaluation U == unsigned - < signed - U > unsigned 8-88 > signed 8U - 88 < unsigned - - > signed (unsigned)- - - > unsigned 8 88U < unsigned 8 (int) 88U > signed 8