Computer Science 15-112, Fall 2012
Class Notes: Data and Expressions
Data and Expressions
Category | Operators |
Arithmetic | +, -, *, /, //, **, %, - (unary), + (unary) |
Relational | <. <=, >=, >, ==, !=, <> |
Bitwise | <<, >>, &, |, ^, ~ |
Assignment | +=, -=, *=, /=, //=, **=, %=, <<=, >>=, &=, |=, ^= |
Logical | and, or, not |
print 2+3*4 # prints 14, not 20 print 9**1/2 # prints 4, not 3
print "20/3 =", (20/3)
print " 6/3 =", ( 6/3)
print " 5/3 =", ( 5/3)
print " 2/3 =", ( 2/3)
print " 0/3 =", ( 0/3)
print "-2/3 =", (-2/3)
print "-3/3 =", (-3/3)
print "-4/3 =", (-4/3)
print "20%3 =", (20%3)
print " 6%3 =", ( 6%3)
print " 5%3 =", ( 5%3)
print " 2%3 =", ( 2%3)
print " 0%3 =", ( 0%3)
print "-2%3 =", (-2%3)
print "-3%3 =", (-3%3)
print "-4%3 =", (-4%3)
print " 3%0 =", ( 3%0)
print 10 / 3
print 10.0 / 3
print 10 / 3.0
x = 10
print x / 3
print 1.0 * x / 3
print float(x) / 3
d1 = 0.1 + 0.1 + 0.1
d2 = 0.3
print (d1 == d2) # False!
print (d2 - d1) # -5.55111512313e-17 (tiny!)
d1 = 0.1 + 0.1 + 0.1
d2 = 0.3
print (d1 == d2) # still false, of course
epsilon = 0.000001
print (abs(d2 - d1) < epsilon) # True!
Once again, using an almostEqual function (that we will write) def almostEqual(d1, d2): epsilon = 0.000001 return (abs(d2 - d1) < epsilon)
d1 = 0.1 + 0.1 + 0.1
d2 = 0.3
print (d1 == d2) # still false, of course
print almostEqual(d1, d2) # True, and now packaged in a handy reusable function!
x = 0
y = 0
print ((y != 0) and ((x/y) != 0)) # Works!
print (((x/y) != 0) and (y != 0)) # Crashes!
Once again, using the "or" operator
x = 0
y = 0
print ((y == 0) or ((x/y) == 0)) # Works!
print (((x/y) == 0) or (y == 0)) # Crashes!
Yet another example:
def isPositive(n): result = (n > 0) print "isPositive(",n,") =", result return result def isEven(n): result = (n % 2 == 0) print "isEven(",n,") =", result return result print "Test 1: isEven(-4) and isPositive(-4)" print (isEven(-4) and isPositive(-4)) # Calls both functions print "----------" print "Test 2: isEven(-3) and isPositive(-3)" print (isEven(-3) and isPositive(-3)) # Calls only one function!
A | B | A and B | not A | not B | (not A) or (not B) | not ((not A) or (not B)) |
0 | 0 | 0 | 1 | 1 | 1 | 0 |
0 | 1 | 0 | 1 | 0 | 1 | 0 |
1 | 0 | 0 | 0 | 1 | 1 | 0 |
1 | 1 | 1 | 0 | 0 | 0 | 1 |
# 0 1 1 0 = 4 + 2 = 6 # 0 1 0 1 = 4 + 1 = 5 print "6 & 5 =", (6&5) print "6 | 5 =", (6|5) print "6 ^ 5 =", (6^5) print "6 << 1 =", (6 << 1) print "6 << 2 =", (6 << 2) print "6 >> 1 =", (6 >> 1) print "~6 =", (~6) print "~6+1 =", (~6+1) // what is going on (see 2's Complement below!) print "~432+1 =", (~432+1) print "Bitwise DeMorgan's Law: a&b == ~(~a|~b)" print "6 & 5 =", (6&5) print "~(~6|~5) =", (~(~6|~5))
def setLower4Bits(n): # SET bits with an OR mask of 1's mask = 0b00001111 # 0x0F (15), or just 0b1111, or just 0xF return n | mask print "setLower4Bits(0b11010110) =", bin(setLower4Bits(0b11010110)) def clearLower4Bits(n): # CLEAR bits with an AND mask of 0's # Error: Due to leading zeroes, this clears all the bits above the 8th bit, too! mask = 0b11110000 # 0xF0 (240) return n & mask print "clearLower4Bits(0b11010110) =", bin(clearLower4Bits(0b11010110)) print "clearLower4Bits(0b101011010110) =", bin(clearLower4Bits(0b101011010110)) // yikes! def clearLower4Bits(n): # CLEAR bits with an AND mask of 0's # Fix: This way, we only clear the lowest 4 bits! mask = ~(0b1111) return n & mask print "clearLower4Bits(0b11010110) =", bin(clearLower4Bits(0b11010110)) print "clearLower4Bits(0b101011010110) =", bin(clearLower4Bits(0b101011010110)) // whew! def getSecondLowestNybble(n): # A 'nybble' is half a 'byte', or 4 bits. # It is a value from 0b0000 (0) to 0b1111 (15). return ((n >> 4) & 0b1111) # or: ((n & 0b11110000) >> 4)
# Note: you may not use conditional expressions until we cover # conditional ("if") statements in a week or two. # They are included here, though, as they are expressions, not statements, # so deserve some mention in the section on expressions.
x = 2 y = 3 if (x < 4) else 5 z = 4 if (x > 4) else 5 print x, y, z
Bits | Decimal Value |
000 | 0 |
001 | 1 |
010 | 2 |
011 | 3 |
100 | -4 |
101 | -3 |
110 | -2 |
111 | -1 |
def negate(x): return (~x + 1) print negate(1); print negate(-1); print negate(0); for x in xrange(12345): assert(negate(x) == -x); assert(negate(negate(x)) == x); print negate(12345678987654321);
# Boolean logic via arithmetic! # These functions demonstrate how you can use (ok, STRETCH) arithmetic # to compute seemingly boolean logical (ie, True/False) functions. # As is standard, we'll use 1 for True and 0 for False. # The functions operate over integer values. # These are not unique -- there are equivalent functions # that use other (possibly more clever) arithmetic approaches. # Still, these work, and provide a glimpse of the # remarkable computational power of good ol' arithmetic. def _not(x): return 1-x def _and(x,y): return x*y def _or(x,y): return x+y-x*y def isNonZero(x): return (x**2+2)%(x**2+1) def isZero(x): return 1-((x**2+2)%(x**2+1)) def isPositive(x): return (1 +(2*x)/(2*x-1))/2 def isNegative(x): return (1 +(2*(-x))/(2*(-x)-1))/2 def isGreaterThan(x, y): return (1 +(2*(x-y))/(2*(x-y)-1))/2 def isLessThan(x, y): return (1 +(2*(y-x))/(2*(y-x)-1))/2 def isEqual(x, y): return 1-(((x-y)**2+2)%((x-y)**2+1)) def testBooleanLogicViaArithmetic(): print "Testing 'boolean logic via arithmetic' functions... ", for x in xrange(-50,50): assert(isZero(x) == (x==0)) assert(isNonZero(x) == (x != 0)) assert(isPositive(x) == (x > 0)) assert(isNegative(x) == (x < 0)) assert(isGreaterThan(x,5) == (x > 5)) assert(isGreaterThan(5,x) == (5 > x)) assert(isLessThan(x,5) == (x < 5)) assert(isLessThan(5,x) == (5 < x)) assert(isEqual(x,5) == (x == 5)) print "passed!" testBooleanLogicViaArithmetic()
def _not(x): return 1-x def _and(x,y): return x*y def _or(x,y): # equivalent to: x+y-x*y return _not(_and(_not(x), _not(y))) # DeMorgan's Law def isNonZero(x): return (x**2+2)%(x**2+1) def isZero(x): # equivalent to: 1-((x**2+2)%(x**2+1)) return _not(isNonZero(x)) def isPositive(x): return (1 +(2*x)/(2*x-1))/2 def isNegative(x): # equivalent to: (1 +(2*(-x))/(2*(-x)-1))/2 # or: _and(_not(isPositive(x), _not(isZero(x)))) return isPositive(-x) def isGreaterThan(x, y): # equivalent to: (1 +(2*(x-y))/(2*(x-y)-1))/2 return isPositive(x-y) def isLessThan(x, y): # equivalent to: (1 +(2*(y-x))/(2*(y-x)-1))/2 return isGreaterThan(y,x) def isEqual(x, y): # equivalent to: 1-(((x-y)**2+2)%((x-y)**2+1)) return isZero(x-y)
# This is a function from the notes on loops (coming soon!), # rewritten here using the techniques above, # and with the variables anonymized to make the # outcome a welcome surprise. Run the code below # to see what it does. All without booleans or (mostly) conditionals. Amazing! def np(n): n += 1 g = 0 while (n): g += 1 c = 0 f = g while (f): c += 1-(((g%f)**2+2)%((g%f)**2+1)) f -= 1 n -= (((1 +(2*(g-1))/(2*(g-1)-1))/2) * (1-(((c-2)**2+2)%((c-2)**2+1)))) return g for n in range(10): print n, np(n)
# Enter these expressions and statements into the interpreter. # Predict the results of each line before advancing to the next line. # Be precise. print 3*3/4, 3/4*3, 3**3/4 x = 1000*1000*1000*1000 # one trillion x print x type(x) x /= 1000*1000*1000 # divide by one billion x x/1000 x x = 123 x.bit_length() import sys x = sys.maxint # 2^31-1, or 2147483647 x.bit_length() x x+1 -x -(x+1) -x-1 -x-2 not 43 not 43/99 43/99 or 99/43 or 99 print 0xff print hex(255) print 255 == 0xff print 255 == hex(255) print "-----------------" x = 5 print 42 if (x == 5) else 99 print ((x == 5) and 42) or 99 print ((x == 5) * 42) + ((x != 5) * 99) print 42 + (x/6)*(99-42) print 42 + ((x-5)*(99-42)) print "-----------------" x = 6 print 42 if (x == 5) else 99 print ((x == 5) and 42) or 99 print ((x == 5) * 42) + ((x != 5) * 99) print 42 + (x/6)*(99-42) print 42 + ((x-5)*(99-42))
carpe diem - carpe diem - carpe diem - carpe diem - carpe diem - carpe diem - carpe diem - carpe diem - carpe diem