MTH 225 Lecture-Module #02:
(Review) Some Basic Math (Algebra, Functions, etc.) Used in Computer Science


selected elements of our textbook's Appendix and Chapter 3 (etc.)
exponentiation, logarithm, factoring, factorial, floor, ...
some of these things you should have seen but may have forgotten details (;-)
    if so it's OK, that's why reviewing, so you'll remember
some of these things or the notation for them here may appear new to you....
all of these things are used misc. places in Computer Science

exponentiation

be a.k.a. 
read "b raised to the power e"
yields b*b*b*···*b where the number of "b"s there is e

e.g. 102 is  which has the value 
e.g. 54 is  which is 
e.g. 28 is 2*2*2*2*2*2*2*2 which is 

Laws of Exponents [p.A7 (in Appendix of our textbook)]:
1.  bx+y  =  bx * by
2.  (bx)y  ==  b(x*y)
(there are further ones; refer to your prior studies of math...)

questions to check familiarity with this material:

  • be + be =?= b(2*e)
    it is true that left-hand side can be simplified


  • 2e + 2e =?= 2(e+1)
    it is true that left-hand side can be simplified

    check:
    28 + 28 == 



    Computer Scientists need to know powers of 2
    (they arise many places such as binary representation, binary sizes of memory, ...)
    as follows:

    obtain higher powers of 2 from those basic ones plus key convenient observation:

    e.g. obtain 231 as follows:
    decompose 31 into 10s plus whatever's left over:
    231 ==  2()
              ==   by Law (i)
    which is 
    which is 
    thus if you ever see some text involving say 231 - 1, you can relatively easily have a sense of how much that is

    logarithm

    inverse of exponentiation is 

    the function logb(z) returns value e such that be == z
    i.e. logb(z) returns the power to which you need to raise b to get z

    e.g. log2(32) returns 
    because  works for the value y in the equation 2y == 32

    e.g. log10(1000) returns 
    e.g. log2(1000) returns 

    Laws of Logarithms [pages A7-8 (in Appendix of our textbook)]:
    0.  b(logb(z)) == z
    0.5  logb(be) == e
    1.  logb(x*y)  ==  logb(x) + logb(y)
    2.  logb(xy) == y*logb(x)
    3.  loga(x) == logb(x)/logb(a)
    (there are further ones; refer to your prior studies of math...
    e.g.  logb(x/y)  ==  logb(x) - logb(y)
    )

    e.g. [0]  2log2(32) := 2 := 

    e.g. [3]  log2(1000) := log10(1000)/log10() := /


    e.g. [1]  consider seeking log5(80000)
    well, note:
    80000 == 8*10*10*10*10
                == 8*()*()*()*()
                ==  (gathering powers)
    then log5(80000)  :=  log5()  :=   by (1)
    which is 

    e.g. [2]  log5(53) := 3*log5(5) := 3*


    notation semi-common in Computer Science:
    "lg(z)" is an abbreviation for "log2(z)"
    e.g. lg(16) := 

    factoring numbers

    some numbers factor into smaller ones
    e.g. 15 := 
    e.g. 42 := 
    e.g. 18 := 
    e.g. 40 := 
    e.g. 64 := 
    some numbers do not factor into smaller ones, in which case we call them 
    e.g. 
    e.g. 
    e.g. 
    (1 not called "prime" because not significant as a factor for other numbers)

    a number n is called "composite" iff .
    e.g. 18 is composite

    to completely/thoroughly factor a number into all its primes,
    first divide out and save all the factors of the first prime ,
    then divide out and save all the factors of the next prime ,
    then divide out and save all the factors of the next prime ,
    then divide out and save all the factors of the next prime ,
    then divide out and save all the factors of the next prime ,
    and so on
    in our textbook, primes less than 100 are listed at bottom page 210 in Section 3.5:
    2, 3, 5, 7, 11, ...

    can easily check divisibility for first three primes 2,3,5:
    * a number is divisible by 2 iff its last digit is 
    * a number is divisible by 3 iff the sum of its digits is divisible by 3
        can repeat if sum of digits isn't one digit
    * a number is divisible by 5 iff 
    to check divisibility by larger primes, you need to do the division and check whether it comes out even
    DON'T BOTHER CHECKING PRIMES WHOSE SQUARES ARE LARGER THAN NUMBER
        if reach this point, number is prime

    e.g. for 24:

    e.g. for 25:

    e.g. for 26:

    e.g. for 

    factorial

    [page 145 in Section 2.3 of our textbook]

    used for counting numbers of permutations, combinations of items
    e.g. when analyzing sorting

    the "factorial" of an integer n, denoted ,
    is the product of all the integers from n down to 1
    e.g. 2! := 2*1 := 
    e.g. 5! := 5*4*3*2*1 := 

    as a special case, 0! is defined to be 
    why isn't 0! := 0?
    well, though it's true that when summing a number of values,
    if the number of values is zero then we get the result ,
    despite that situation with summing,
    when multiplying a number of values,
    if the number of values is zero then we get the result 
    e.g.:
        23 = 2*2*2 := 
        22 = 2*2 := 
        21 = 2 := 
        20 = _ := 
    as if there's always an implicit "*1" or something
    similarly:
        3! = 3*2*1 := 
        2! = 2*1 := 
        1! = 1 := 
        0! = _ := 
    if the choice were different,
    various properties would break down
    e.g. that 2e+1 = 2*2e :
        23 = 2*22
        22 = 2*21
        21 = 2*20
    and similarly (n+1)! = (n+1)*n! :
        3! = 3*2!
        2! = 2*1!
        1! = 1*0!

    floor, ceiling

    [pages 142-45 in Section 2.3 of our textbook]

    these are Mathematicians' notations for ~~rounding/truncation of floating-point number to integer -- down or up

    ⌊x⌋ denotes the "floor" of x a.k.a. 
        (for not-quite-up-to-date Web-browsers:  |_x_| )
    which is the greatest integer less than or equal to x
    ⌈x⌉ denotes the "ceiling" of x a.k.a. 
        (for not-quite-up-to-date Web-browsers:  |¯x¯| )
    which is the least integer greater than or equal to x

    e.g.  ⌊1.414⌋  := 
        (for not-quite-up-to-date Web-browsers:  |_1.414_| )
    e.g.  ⌊1.618⌋  := 
        (for not-quite-up-to-date Web-browsers:  |_1.618_| )
    e.g.  ⌈1.414⌉  := 
        (for not-quite-up-to-date Web-browsers:  |¯1.414¯| )
    e.g.  ⌈1.618⌉  := 
        (for not-quite-up-to-date Web-browsers:  |¯1.618¯| )

    e.g. usage: floor "⌊x⌋" used often in programs using "|(int)|" to convert |double| to |int|

    e.g. application for ceiling "⌈x⌉":
    * pigeonhole principle (presented later)
    * when searching a list using binary search, how many times may compare against the target
        ⌈lg(list.length)⌉

    e.g. what may be the number of days between two times given in milliseconds

    well, the number of ms per day is
        1000ms/s * 60s/m * 60m/h * 24h/d := ms/d
    then 
    but if the time-difference in days is ,
    do you say the number of days between the two times is 57 or 58??
    using floor,  ⌊57.87...⌋  := 
        (for not-quite-up-to-date Web-browsers:  |_57.87_| )
    using ceiling,  ⌈57.87...⌉  := 
        (for not-quite-up-to-date Web-browsers:  |¯57.87¯| )


    quotient, remainder/modulus

    [pages 200ff. in Section 3.4 of our textbook]

    basic features of division for integers:

    "division algorithm":
    the issue is, how can you do division
    if you don't already know it
    but have simpler operations such as + and - ?
    divide integer a by positive divisor d by
    repeatedly subtracting d from a (using r for intermediate values)
        while using  q  to count number of subtractions done
    until left with remainder r less than d.
    the results are the final values of:
    * q, which is the quotient — the number of times d can be taken away from a; and
    * r, the remainder
    Note:
    I won't be requiring you to write code like this in this course (MTH 225).
    But I do expect you to be able to understand it,
    considering this course's ~~prerequisite CS 162.
        int[] division_algorithm(int n, int d) {
            if ( d <= 0 )
                throw new IllegalArgumentException("divisor should be positive");
            int q = 0, r = n;
            // typically, reduce high value, until remainder is less than |d|:
            while ( d <= r ) {
                r -= d;
                q++;
                }
            // alternatively, if value was negative, increase until not negative:
            while ( r < 0 ) {
                r += d;
                q--;
                }
            int[] results = {q, r};
            return  results;
            }
    
    (our textbook presents somewhat different version page 225)

    like CS 251 MIPS computer instruction  div
    yields quotient in one register, remainder in another

    e.g. (3rd grade?) divide 126 by 23:


    note quotient q := ⌊n/d⌋
        (for not-quite-up-to-date Web-browsers:  |_ n / d _| )
    e.g. 48/5 :=  ; ⌊48/5⌋  :=  ⌊⌋  :=  
        (for not-quite-up-to-date Web-browsers:  |_ 48 / 5 _|  :=  ... )
    (when doing division of two declared integers,
    Java and other programming languages automatically yield integer truncation like that
    instead of real n/d
    but handling negative values maybe more as you would expect)

    more abstractly (i.e. instead of referring to that primitive algorithm),
    if n is any integer and d is a positive integer
    then dividing n by d yields unique integers q and r
        with r one of the values {0,1,2,..,(d-2),(d-1)}
    such that  n  ==  d*q + r
    we call q the "quotient" and r the "remainder"
    e.g. dividing n=48 by d=5 yields q :=  and r := 
    satisfying  (n=48)  ==  (d=5)*(q=) + (r=)
        and  (r=) being one of the values {0,1,2,...,(d-2=),(d-1=)}
    and there are no other possibilities for q and r satisfying the conditions
    notably that r must be one of the values {0,1,2,..,(d-2),(d-1)}
    don't say dividing n=48 by d=5 yields q := 10 and r := -2

    e.g. dividing n=52 by d=3 yields q :=  and r := 
    e.g. dividing n=64 by d=8 yields q :=  and r := 

    e.g. dividing n = -25 by d = 7 yields q :=  and r := 
    the values for r being considered here are only {0,1,2,...,(d-2=),(d-1=)}
        not considering possible negative values for r
    which forces q :=  and r := 
    satisfying  (n=-25)  ==  (d=7)*(q=) + (r=)
    again note quotient q := ⌊n/d⌋
        (for not-quite-up-to-date Web-browsers:  |_ n / d _| )
    e.g. (-25)/7 :=  ; ⌊(-25)/7⌋  :=  ⌊⌋  :=  
        (for not-quite-up-to-date Web-browsers:  |_ (-25) / 7 _|  :=  ... )


    actually we'll focus more on remainder (r) than quotient
    further special notation for it is as follows:
    "n  d" returns the remainder r obtained as above
    here "mod" may be read 
    and d called the "modulus"
        so might use identifier  instead of "d"
    this operation called "modulus operation"
    e.g.  27 mod 5 := 
    e.g.  21 mod 7 := 
    (in Java as well as in C++ and C, can use  for "mod"
    but again whereas here consider only nonnegative remainders,
    in a program  %  can yield negative value if operands are negative
    (probably because such a scheme easier to implement))

    application of mod:
    consider game such as  Minesweeper
    program places mines at apparently randomly chosen locations
        (5,2), (6,3), (0,7), ...
    how obtain those random values 5, 2, 6, 3, 0, 7, ...?
    "linear congruential method" provides such pseudo-random integers x0, x1, x2, x3, ... as follows
    start with seed s say (last few digits of) current time
    e.g. 
    have modulus say 2000
    multiplier μ say 101,
    increment c say 997
    start x0 := s
    then generate succesive apparently random integers as follows:
        xnext :=  (μ*xprev + c) mod m
    e.g. x1 :=  (101* + 997) mod 2000
                    :=  ( + 997) mod 2000
                    :=   mod 2000
                    :=  
    e.g. x2 :=  (101* + 997) mod 2000
                    :=  ( + 997) mod 2000
                    :=   mod 2000
                    :=  
    e.g. x3 :=  (101* + 997) mod 2000
                    :=  ( + 997) mod 2000
                    :=   mod 2000
                    :=  
    e.g. x4 :=  (101* + 997) mod 2000
                    :=  ( + 997) mod 2000
                    :=   mod 2000
                    :=  
    e.g. x5 :=  (101* + 997) mod 2000
                    :=  ( + 997) mod 2000
                    :=   mod 2000
                    :=  
    thus x0 := , x1 := , x2 := , x3 := , x4 := , x5 := , ...
    system maintains sequence of x-values like that behind the scenes
    so if you request a random number between 0 and a small value k,
        e.g. if you use Java Random.nextInt(k)
    then system gives you  xcurrent mod k  i.e.  x_current % k
    e.g. if k is 10
    mod 10  yields  
    mod 10  yields  
    mod 10  yields  
    mod 10  yields  
    mod 10  yields  
                                            ·
                                            ·
                                            ·
    will appear random
    except sequence will repeat
        ... xm-2, xm-1, xm=x0, xm+1=x1, xm+2=x2, ...
    so called "pseudo"-random
    computer-systems' pseudorandom number generators use very large m to stave this off



    &~&~digressions

    ~~digression part 1. "A Little 'Arithmancy'"
    in-class activity
    getting started thinking more consciously about number representation
    than you might otherwise

    [Acknowledgement: I learned this trick from Pablo Trefftz]

    I'm such a fan of the Harry Potter books
    such as
    that I can do Arithmancy with such.
    Each of you choose a three-digit number say a  whose digits from left to right are descending
    e.g. 987 or 421 or 530
    but not 123 nor 767 nor 007 (—not truly three-digit)
    Let b  be the reverse of  a; write b  under a.
    e.g.  987
          789
    Perform the subtraction  a - b, obtaining say c.
    e.g.  987 - 789 = ...
    Then let d  be the reverse of that last result c; write d  under c.
    Perform the addition  c + d , obtaining say e.

    Now a volunteer is needed.  

    Volunteer, let f  be the number obtained from the first three digits of your number e, and let g  be the last digit.
    Look at page number f  in this book, and on this page count down g  lines.
    Concentrate on the word at the front of that line...
    Is it ?



    Explication of the math:

    Let  H,  T, and  U  denote the three digits of the initial three-digit number a
    so  a = 100*H + 10*T + 1*U  and  9 ≥ H > T > U ≥ 0
    The reverse of  a, namely  b, is  UTH; i.e.  b = 100*U + 10*T + 1*H.
    Then  c :=  a - b  =  .
    Let  X := H - U. Then note  9 ≥ X ≥ 2.
    Then  c =  .
    Or, doing the 'borrowing' from higher-order digits that is standard during subtraction,
    c =  .
    Then the reverse of  c, namely  d, is .
    Then  e :=  c + d  =    =  ,
    i.e.  e  is .
    And then  f  is  and g is .
    Knowing all this in advance, for this trick you need to memorize just one word from the book.



    The point of that activity is to raise your awareness about (decimal) number representation
    to prepare for the next activities.



    ~~digression part 2. "A Little Binary"

    rem. puzzle of first lecture:

      Suppose the following:
      * You have an employee who is supposed to work for you for seven days.
      * The salary for this employee is supposed to be one ounce of gold per day.
      * You have a seven-ounce brick of gold.
      * Instead of waiting till the end of the seven days to pay the total salary,
          the employee should have one ounce by the end of the first day,
          two ounces by the end of the second day,
          three ounces by the end of the third day,
          and so on.
      * The brick of gold has graduated one-ounce marking lines as follows:
          +---+---+---+---+---+---+---+
          |   .   .   .   .   .   .   |
          |   .   .   .   .   .   .   |
          |   .   .   .   .   .   .   |
          +---+---+---+---+---+---+---+
      * The only way you can divide the brick of gold is by using a saw which you
          have to make straight cuts along those graduated marking lines.
      * You do not want to make more than two cuts (because cutting causes
          loss of gold sawdust).
    


    as mentioned that day,
    what's happening here is actually

    whereas we (humans) typically represent numbers using decimal sequences of digits
        involving powers of ten
    with ..., a hundreds place, a tens place, and a ones place,
    (see digression 1 above),
    binary also works
        involving powers of two
    with ..., a fours place, a twos place, and a ones place:
    decimal | binary
    --------+-------
         1  |  001
         2  |  010
         3  |  011
         4  |  100
         5  |  101
         6  |  110
         7  |  111
       ...  |  ...
    
    that chart shows how each decimal number from 1 to 7 can be represented by an appropriate combination of the three values 4, 2, and 1
    (just as every number from 1 to 999 can be represented by some appropriate combination of the values 100,10,1).

    binary representation
        which I'll be discussing below
    is important for Computer Science.



    ~~digression part 3: "A Little Ternary"

    Computer Science uses further number representations, particularly hexadecimal and octal.
    Though this third activity doesn't involve them,
    the point is to make you aware that there can be further number representations
    in addition to base ten, base two

    [Acknowledgement: I learned about this puzzle from Andy Felt.]

    A farmer had a 40-pound rock used as a counterweight on scales to measure weights of containers of produce. A 'friend' borrowed the rock, but they dropped it, and it broke into four pieces. The farmer said, "That's OK: actually now I can achieve weights equal to every number up to 40."

    What are the weights of the pieces?

    Solution: 

    Mathematical explication: 


    binary representation of integers

    (Section 3.6 of our textbook)

    need to know this material to be able to understand how computers encode all data

    well, remembering back to ,
    what is the interpretation of our normal decimal i.e. base-ten representation of integers?
    digits are 
    e.g.   397ten has 3 in 100s place, 9 in 10s place, 7 in 1s place
    i.e.   397ten  ==  
    I use notation "di" for the digit in the 10i place
    e.g. for 397ten,  d0,  d1,  d2

    why might decimal representation concern any of you now?
    well, someone has to implement  Integer.toString(int)
    which depends on handling (individual) digits; what if it's you?
    public class ... {
        public static void main(String[] args) {
            int n_given = new Random() .nextInt(1000);
            System.out.println("n_given's digit d0: " + digit(n_given, 0));
            System.out.println("n_given's digit d1: " + digit(n_given, 1));
            System.out.println("n_given's digit d2: " + digit(n_given, 2));
            }
    
    for each of a given number ngiven's digits di corresponding to our base's powers 10i,
    di := ⌊ngiven / 10i⌋ mod 10
        (for not-quite-up-to-date Web-browsers:  ... |_ ngiven / 10i _| ...)
        public static int digit(int n_given, int place) {
            
            }
        }
    
    e.g. ⌊397 / 100⌋ mod 10 := ⌊397/⌋ mod 10 := ⌊⌋ mod 10 :=  which is d0
    e.g. ⌊397 / 101⌋ mod 10 := ⌊397/⌋ mod 10 := ⌊⌋ mod 10 :=  mod 10 :=  which is d1
    e.g. ⌊397 / 102⌋ mod 10 := ⌊397/⌋ mod 10 := ⌊⌋ mod 10 :=  mod 10 :=  which is d2

    anyway, people(/computers) have used and still use some bases other than ten

    ancient Babylonians used base sixty(!)

    various LINUX/UNIX utilities such as access-control use
    base-eight representation called 
    for base eight, digits are 
    e.g. 162eight  ==  1*82 + 6*81 + 2*80
                            ==  tententen
                            ==  ten

    and Computer Science also uses hexadecimal which is base 
    used for compactness and convenient conversion with the following base:

    fundamental base Computer Science uses is 
    ultimately because it's easiest to build machines processing data represented this way
    this was an insight of  in 1945:
    The all-or-none, two-equilibrium arrangements [of electronic components] are [best]. [Then] it is natural to use a system of arithmetic in which the digits are also two-valued.
    "First Draft of a Report on the EDVAC [Electronic Discrete Variable Automatic Computer]"
    in that paper, von Neumann specified further basic features for design of computers
    e.g. central arithmetic unit, memory, stored program, ...
    all computers now conform to that design called "von Neumann architecture"

    anyway,
    base-two arithmetic called 
    for base two, digits are only 
    abbreviates "binary digit"
    e.g. 110two 
    i.e. 110two  ==  1*22 + 1*21 + 0*20
                        ==  tententen
                        ==  ten
    (reversing:   ten == 110two)
    e.g. 1001011two 
    i.e. 1001011two  ==  1*26 + 0*25 + 0*24 + 1*23 + 0*22 + 1*21 + 1*20
                              ==  ten +                    + ten +         + tenten
                            ==  ten
    (reversing:   ten == 1001011two)
    thus can obtain decimal representation of a number presented in binary

    like with base ten above,
    for each of a given number ngiven's binary digits bi corresponding to powers 2i,
        e.g. for 1001011two,  b0,  b1,  b2,
            b3,  b4,  b5,  b6
    bi := ⌊ngiven / 2i⌋ mod 2
        (for not-quite-up-to-date Web-browsers:  ... |_ ngiven / 2i _| ...)
    e.g. for b0 ⌊75 / 20⌋ mod 2 := ⌊75/⌋ mod 2 := ⌊⌋ mod 2 :=  which is b0
    e.g. for b1 ⌊75 / 21⌋ mod 2 := ⌊75/⌋ mod 2 := ⌊⌋ mod 2 :=  mod 2 :=  which is b1
    e.g. for b2 ⌊75 / 22⌋ mod 2 := ⌊75/⌋ mod 2 := ⌊⌋ mod 2 :=  mod 2 :=  which is b2
    incidentally, notice that ⌊75 / 22⌋ == ⌊⌊75 / 21⌋ / 2⌋
    and we had already calculated ⌊75 / 21
    generally, ⌊u / ve+1⌋ == ⌊⌊u / ve⌋ / v⌋
        (as  u/ve+1 == (u/ve)/v )
    enabling us to do these evaluations more easily as follows:
    e.g. ⌊75 / 23⌋ mod 2 := ⌊⌊75 / 22⌋ / 2⌋ mod 2 := ⌊ / 2⌋ mod 2 := ⌊⌋ mod 2 :=  mod 2 :=  which is b3
    e.g. ⌊75 / 24⌋ mod 2 := ⌊⌊75 / 23⌋ / 2⌋ mod 2 := ⌊ / 2⌋ mod 2 :=  mod 2 :=  which is b4
    e.g. ⌊75 / 25⌋ mod 2 := ⌊⌊75 / 24⌋ / 2⌋ mod 2 := ⌊ / 2⌋ mod 2 :=  mod 2 :=  which is b5
    e.g. ⌊75 / 26⌋ mod 2 := ⌊⌊75 / 25⌋ / 2⌋ mod 2 := ⌊ / 2⌋ mod 2 :=  mod 2 :=  which is b6

    such processing actually provides algorithm for obtaining binary representation of a number presented in decimal
    here's ≈Java encoding of this algorithm:
    (≈p.221 in our textbook)
    Note:
    I won't be requiring you to write code like this in this course (MTH 225).
    But I do expect you to be able to understand it,
    considering this course's ~~prerequisite CS 162.
        void base_2_expansion(int n, int[] b) {    // resulting bits stored in |b[]|
                                                // i.e. this code will set |b[]|
                                                // to be {...,1,0,1,1,0,0,...}
                                                // as appropriate
            // let |ngiven| denote the initial given value for e
            int k = 0;
            while ( n > 0 ) {
                // at this point n == ⌊ngiven/2n⌋
                b[k] = n % 2;
    
                n = n/2;    // in Java, division of |int|s automatically does floor
                            // so this statement |n = n/2;| resets n
                            // to: ⌊⌊ngiven / 2k⌋ / 2⌋
                            // which is: ⌊ngiven / 2(k+1)⌋
                k = k + 1;  // then with k changed here to k + 1,
                            // n == ⌊ngiven / 2k⌋ for the new k
                }
            // assume |b[]| otherwise contains zeroes
            }
    
    e.g. what may be binary representation of 98ten?
    98    =  . . . ?0?or?1?  ?0?or?1?  ?0?or?1?  ?0?or?1?  ?0?or?1?  ?0?or?1?
     [ten]         --------  --------  --------  --------  --------  -------- [two]
                    25=32     24=16      23=8      22=4      21=2      20=1
                    place     place     place     place     place     place
    
    invoke  base_2_expansion(98, int_array)  as follows:
        void base_2_expansion(int n, int[] b) {
            // let |ngiven| denote the initial given value for n: 
            int k = 0;
            while ( n > 0  )
                {
                // at this point n == ⌊ngiven/2n⌋  i.e.  98 == ⌊98/20⌋
                b[k] = n % 2;     // b[0] = 98 % 2 ;
                n = n/2 ;
                k = k + 1 ;
                }
            while ( n > 0  )
                {
                // at this point n == ⌊ngiven/2n⌋  i.e.  49 == ⌊98/21⌋
                b[k] = n % 2;     // b[1] = 49 % 2 ;
                n = n/2 ;
                k = k + 1 ;
                }
            while ( n > 0  )
                {
                // at this point n == ⌊ngiven/2n⌋  i.e.  24 == ⌊98/22⌋
                b[k] = n % 2;     // b[2] = 24 % 2 ;
                n = n/2 ;
                k = k + 1 ;
                }
            while ( n > 0  )
                {
                // at this point n == ⌊ngiven/2n⌋  i.e.  12 == ⌊98/23⌋
                b[k] = n % 2;     // b[3] = 12 % 2 ;
                n = n/2 ;
                k = k + 1 ;
                }
            while ( n > 0  )
                {
                // at this point n == ⌊ngiven/2n⌋  i.e.  6 == ⌊98/24⌋
                b[k] = n % 2;     // b[4] = 6 % 2 ;
                n = n/2 ;
                k = k + 1 ;
                }
            while ( n > 0  )
                {
                // at this point n == ⌊ngiven/2n⌋  i.e.  3 == ⌊98/25⌋
                b[k] = n % 2;     // b[5] = 3 % 2 ;
                n = n/2 ;
                k = k + 1 ;
                }
            while ( n > 0  )
                {
                // at this point n == ⌊ngiven/2n⌋  i.e.  1 == ⌊98/26⌋
                b[k] = n % 2;     // b[6] = 1 % 2 ;
                n = n/2 ;
                k = k + 1 ;
                }
            while ( n > 0  )
            }
    
    summarizing,
    i.e. 98ten  ==  *26*25*24*23*22*21*20
                    ==  two



    application of binary representation of integers:
    repeated squaring algorithm good way to do exponentiation

    a straightforward way to do exponentiation is as follows:
    the following code is supposed to return ae:
    Note:
    I won't be requiring you to write code like this in this course (MTH 225).
    But I do expect you to be able to understand it,
    considering this course's ~~prerequisite CS 162.
    int exponentiation(int a, int e) {
        
        }
    
    note loop repeats e times
    thus do operations in the loop such as the important multiplication e times

    well consider what occurs in cryptographic secure communication:
    a message such as "HI" represented as number a e.g. a=0910
    and then need to calculate ae (modulo another value m)
    where e is a number such as the following:
    692,469,504,614,203,622,460,465,868,734,959,711,852,932,318,
    302,149,455,793,493,889,446,970,470,508,640,328,165,696,445,
    236,740,914,740,354,470,714,166,287,934,901,598,998,105,531,
    316,760,680,771,813

    the number of seconds required by a computer to do e multiplications would be at least the following:
    692,469,504,614,203,622,460,465,868,734,959,711,852,932,318,
    302,149,455,793,493,889,446,970,470,508,640,328,165,696,445,
    236,740,914,740,354,470,714,166,287,934,901,598,998,105,531,
    316,760 s.
    in years that's more than the following:
    692,469,504,614,203,622,460,465,868,734,959,711,852,932,318,
    302,149,455,793,493,889,446,970,470,508,640,328,165,696,445,
    236,740,914,740,354,470,714,166,287,934,901,598,998,105 y.

    instead of that,
    repeated squaring algorithm faster way to calculate ae
    even with that value of e
    loop (shown below) will repeat only  times(!)
    which requires only a fraction of a second

    to understand this algorithm,
    consider first a simple example:
  • suppose e is 8192
    and suppose the following operations are performed:
      sqrrep := a;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
    
    at that point have ae — doing only  operations, not 8192(!)

    what if e is 139264 which is  131072 + 8192 ?

      result := 1;
      sqrrep := a;
        // now sqrrep is a1 which is a20
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a2 which is a21
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a4 which is a22
      ·
      ·
      ·
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a8192 which is a213
      result := result * sqrrep;
        // now result is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      sqrrep := sqrrep * sqrrep;
        // now sqrrep is a which is a2
      result := result * sqrrep;
    
    at the end here that last multiplication  result * sqrrep
    is  a8192 * a131072 (which is  a213 * a217 )
    which equals a (which is  a)
        by Law 1 of Exponents
    which equals a139264 i.e. ae which was desired
    (incidentally note that e=139264ten == 100010000000000000two
    and the binary representation reflects that e is  1*217 + 1*213 )

    the repeated squaring algorithm for calculating ae generalizes from the preceding examples:
    start  result  at 1 and  sqrrep  at a ;
    repeatedly square  sqrrep  so  sqrrep  holds values of a raised to successive powers of two;
    and include value of  sqrrep  in  result  if e contains the corresponding power of two.
    here's Java encoding of this algorithm:
    int exponentiation(int a, int e) {
        int result = 1;
        int sqrrep = a;
        while ( e > 0 ) {
            // e == ⌊egiven / 2i⌋  and  sqrrep == a2i
            if ( e % 2 == 1 )     // as above with binary representation
                                    // this condition corresponds
                                    // to egiven containing 2i
                result = result * sqrrep;    // so make |result| contain sqrrep == a2i
            sqrrep = sqrrep * sqrrep;        // advance sqrrep to a2(i+1)
            e = ⌊e/2⌋;              // advance e to ⌊egiven/2(i+1)⌋
            }
        return  result;
        }
    
    as above when determining binary representation,
    e % 2 == 1  holds iff egiven contains corresponding 2i ;
    and (as indicated in examples for 8192 etc. above),
    sqrrep is the corresponding a2i


    incidentally, further for cryptography,
    we may not care about full  result  so much as result mod another number m
    in this case actually do  mod m  different times during the algorithm
    as shown in our textbook by Rosen p.226 (Algorithm 5)

    e.g. to calculate 91027 mod 2001
    don't straightforwardly start 91027 (= )
        that would lose precision
        (even if not with this relatively small example exponent 27,
        consider more realistic large exponent indicated above)
    int modular_exponentiation(
        int a, int e, int m     // a := , e := , m := 
        )
      {
      int result = 1;           // result := 
      int sqrrep = a % m;       // sqrrep :=   %   :=  
      while ( e > 0 ) {         //  > 0  :=  
        if ( e % 2 == 1 )       //  % 2 == 1  :=   == 1  :=  
          result = result * sqrrep % m;
                                // result :=   *  % 
                                //        :=   % 
                                //        :=  
        sqrrep = sqrrep * sqrrep % m;
                                // sqrrep :=   *  % 
                                //        :=   % 
                                //        :=  
        e = ⌊e/2⌋;              // e :=  ⌊/2⌋  :=  ⌊⌋  :=  
        }
      while ( e > 0 ) {         //  > 0  :=  
        if ( e % 2 == 1 )       //  % 2 == 1  :=   == 1  :=  
          result = result * sqrrep % m;
                                // result :=   *  % 
                                //        :=   % 
                                //        :=  
        sqrrep = sqrrep * sqrrep % m;
                                // sqrrep :=   *  % 
                                //        :=   % 
                                //        :=  
        e = ⌊e/2⌋;              // e :=  ⌊/2⌋  :=  ⌊⌋  :=  
        }
      while ( e > 0 ) {         //  > 0  :=  
        if ( e % 2 == 1 )       //  % 2 == 1  :=   == 1  :=  
          result = result * sqrrep % m;
        sqrrep = sqrrep * sqrrep % m;
                                // sqrrep :=   *  % 
                                //        :=   % 
                                //        :=  
        e = ⌊e/2⌋;              // e :=  ⌊/2⌋  :=  ⌊⌋  :=  
        }
      while ( e > 0 ) {         //  > 0  :=  
        if ( e % 2 == 1 )       //  % 2 == 1  :=   == 1  :=  
          result = result * sqrrep % m;
                                // result :=   *  % 
                                //        :=   % 
                                //        :=  
        sqrrep = sqrrep * sqrrep % m;
                                // sqrrep :=   *  % 
                                //        :=   % 
                                //        :=  
        e = ⌊e/2⌋;              // e :=  ⌊/2⌋  :=  ⌊⌋  :=  
        }
      while ( e > 0 ) {         //  > 0  :=  
        if ( e % 2 == 1 )       //  % 2 == 1  :=   == 1  :=  
          result = result * sqrrep % m;
                                // result :=   *  % 
                                //        :=   % 
                                //        :=  
        sqrrep = sqrrep * sqrrep % m;
                                // sqrrep :=   *  % 
                                //        :=   % 
                                //        :=  
        e = ⌊e/2⌋;              // e :=  ⌊/2⌋  :=  ⌊⌋  :=  
        }
      while ( e > 0 ) {         //  > 0  :=  
    
      return  result;           // return 
      }
    
    secure communication would transmit 0211 instead of 0910 ("HI")



    but then what?
    well, receiver would calculate  (211867) mod 2001  :=  

    the receiver needs to know 
    stay tuned for explanation of that in next lecture-module


    (Copyright © 2008 by Hugh McGuire   — for thoughts about this, see   http://www.cis.gvsu.edu/~mcguire/teaching/copyright_thoughts.html .)