Itera&on
Need
one
more
concept
to
be
able
to
write
programs
of
arbitrary
complexity
Start
with
a
test
If
evaluates
to
True,
then
execute
loop
body
once,
and
go
back
to
reevaluate
the
test
Repeat
un&l
test
evaluates
to
False,
a?er
which
code
following
itera&on
statement
is
executed
An
example
x = 3!
ans = 0!
itersLeft = x!
while (itersLeft != 0):!
ans = ans + x!
itersLeft = itersLeft 1!
print(str(x) + '*' + str(x) + ' = ' + str(ans))!
!
This
code
squares
the
value
of
x
by
repe&&ve
addi&on.
Stepping
through
this
code
x = 3!
ans = 0!
itersLeft = x!
while (itersLeft != 0):!
ans = ans + x!
itersLeft = itersLeft 1!
print(str(x) + '*' + str(x) +
' = ' + str(ans))!
ans
itersLe+
Some
proper&es
of
itera&on
loops:
need
to
set
an
itera&on
variable
outside
the
loop
need
to
test
that
variable
to
determine
when
done
need
to
change
that
variable
within
the
loop,
in
addi&on
to
other
work
Itera&ve
code
Branching
structures
(condi&onals)
let
us
jump
to
dierent
pieces
of
code
based
on
a
test
Programs
are
constant
.me
Looping
structures
(e.g.,
while)
let
us
repeat
pieces
of
code
un&l
a
condi&on
is
sa&sed
Programs
now
take
&me
that
depends
on
values
of
variables,
as
well
as
length
of
program
Classes
of
algorithms
Itera0ve
algorithms
allow
us
to
do
more
complex
things
than
simple
arithme0c
We
can
repeat
a
sequence
of
steps
mul0ple
0mes
based
on
some
decision;
leads
to
new
classes
of
algorithms
One
useful
example
are
guess
and
check
methods
Guess
and
check
Remember
our
declara0ve
deni0on
of
square
root
of
x!
If
we
could
guess
possible
values
for
square
root
(call
it
g),
then
can
use
deni0on
to
check
if
g*g = x!
We
just
need
a
good
way
to
generate
guesses
Finding
a
cube
root
of
an
integer
One
way
to
use
this
idea
of
genera0ng
guesses
in
order
to
nd
a
cube
root
of
x is
to
rst
try
0**3,
then
1**3,
then
2**3,
and
so
on
Can
stop
when
reach
k such
that
k**3 > x!
Only
a
nite
number
of
cases
to
try
Some
code
x = int(raw_input('Enter an integer: '))!
ans = 0!
while ans**3 < x:!
ans = ans + 1!
if ans**3 != x:!
print(str(x) + ' is not a perfect cube')!
else:!
print('Cube root of ' + str(x) + ' is '
+ str(ans))!
Extending
scope
Only
works
for
posi0ve
integers
Easy
to
x
by
keeping
track
of
sign,
looking
for
solu0on
to
posi0ve
case
Some
code
x = int(raw_input('Enter an integer: '))!
ans = 0!
while ans**3 < abs(x):!
ans = ans + 1!
if ans**3 != abs(x):!
print(str(x) + ' is not a perfect cube')!
else:!
if x < 0:!
ans = - ans!
print('Cube root of ' + str(x) + ' is '
+ str(ans))!
Loop
characteris0cs
Need
a
loop
variable
Ini0alized
outside
loop
Changes
within
loop
Test
for
termina0on
depends
on
variable
Useful
to
think
about
a
decremen'ng
func'on
Maps
set
of
program
variables
into
an
integer
When
loop
is
entered,
value
is
non-nega0ve
When
value
is
<=
0,
loop
terminates,
and
Value
is
decreased
every
0me
through
loop
Here
we
use
abs(x) ans**3!
What
happens
if
we
miss
a
condi0on?
Suppose
we
dont
ini0alize
the
variable?
Suppose
we
dont
change
the
variable
inside
the
loop?
Exhaus0ve
enumera0on
Guess
and
check
methods
can
work
on
problems
with
a
nite
number
of
possibili0es
Exhaus0ve
enumera0on
is
a
good
way
to
generate
guesses
in
an
organized
manner
For
loops
While loops
generally
iterate
over
a
sequence
of
choices
(ints in
cases
we
have
seen)
Python
has
a
specialized
mechanism
for
this
case,
called
a
for loop
for <identifier> in <sequence>:!
<code block> !
For
loops
Iden>er
bound
to
rst
value
in
sequence
Code
block
executed
Iden>er
bound
to
next
value
Code
block
executed
Con>nues
un>l
sequence
exhausted
or
a
break
statement
is
executed
To
generate
a
sequence
of
integers,
use
range(n) = [0, 1, 2, 3, , n-1]!
range(m,n) = [m, m+1, , n-1]!
A
cleaned
up
cube
root
nder
x = int(raw_input('Enter an integer: '))!
for ans in range(0, abs(x)+1):!
if ans**3 == abs(x):!
break!
if ans**3 != abs(x):!
print(str(x) + ' is not a perfect
cube')!
else:!
if x < 0:!
ans = - ans!
print('Cube root of ' + str(x) + ' is
' + str(ans))!
Dealing
with
oats
Floats
approximate
real
numbers,
but
useful
to
understand
how
Decimal
number:
302
=
3*10**2
+
0*10**1
+
2*10**0
Remember:
**
is
Pythons
exponenMaMon
operator
Binary
number
10011
=
1*2**4
+
0*2**3
+
0*2**2
+
1*2**1
+
1*2**0
(which
in
decimal
is
16
+
2
+
1
=
19)
Internally,
computer
represents
numbers
in
binary
ConverMng
decimal
integer
to
binary
Consider
example
of
x
=
1*2**4
+
0*2**3
+
0*2**2
+
1*2**1
+
1*2**0
If
we
take
remainder
relaMve
to
2
(x%2) of
this
number,
that
gives
us
the
last
binary
bit
If
we
then
divide
x
by
2
(x/2),
all
the
bits
get
shiQed
leQ
x/2
=
1*2**3
+
0*2**2
+
0*2**1
+
1*2**0
=
1001
Keep
doing
successive
divisions;
now
remainder
gets
next
bit,
and
so
on
Lets
convert
to
binary
form
Doing
this
in
Python
if num < 0:!
isNeg = True!
num = abs(num)!
else:!
isNeg = False!
result = !
if num == 0:!
result = 0!
while num > 2:!
result = str(num%2) + result!
num = num/2!
if isNeg:!
result = - + result!
So
what
about
fracMons?
3/8
=
0.375
=
3*10**(-1)
+
7*10**(-2)
+
5*10**(-3)
So
if
we
mulMply
by
a
power
of
2
big
enough
to
convert
into
a
whole
number,
can
then
convert
to
binary,
then
divide
by
the
same
power
of
2
0.375
*
(2**3)
=
3
(decimal)
Convert
3
to
binary
(now
11)
Divide
by
2**3
(shiQ
leQ)
to
get
0.011
(binary)
x = float(raw_input('Enter a decimal number between 0 and 1: '))!
!
p = 0!
while ((2**p)*x)%1 != 0:!
print('Remainder = ' + str((2**p)*x - int((2**p)*x)))!
p += 1!
!
num = int(x*(2**p))!
!
result = ''!
if num == 0:!
result = '0'!
while num > 0:!
result = str(num%2) + result!
num = num/2!
!
for i in range(p - len(result)):!
result = '0' + result!
!
result = result[0:-p] + '.' + result[-p:]!
print('The binary representation of the decimal ' + str(x) + ' is
' + str(result))!
!
Some
implicaMons
If
there
is
no
integer
p
such
that
x*(2**p)
is
a
whole
number,
then
internal
representaMon
is
always
an
approximaMon
Suggest
that
tesMng
equality
of
oats
is
not
exact
Use
abs(x-y)
<
0.0001,
rather
than
x
==
y
Why
does
print(0.1)
return
0.1,
if
not
exact?
Because
Python
designers
set
it
up
this
way
to
automaMcally
round
Approximate
solu/ons
Suppose
we
now
want
to
nd
the
square
root
of
any
non-nega/ve
number?
Cant
guarantee
exact
answer,
but
just
look
for
something
close
enough
Start
with
exhaus/ve
enumera/on
Take
small
steps
to
generate
guesses
in
order
Check
to
see
if
close
enough
Example
code
x = 25!
epsilon = 0.01!
step = epsilon**2!
numGuesses = 0!
ans = 0.0!
while (abs(ans**2 - x)) >= epsilon and ans <= x:!
ans += step!
numGuesses += 1!
print('numGuesses = ' + str(numGuesses))!
if abs(ans**2-x) >= epsilon:!
print('Failed on square root of ' + str(x))!
else:!
print(str(ans) + ' is close to the square root
of ' + str(x))!
Some
observa/ons
Step
could
be
any
small
number
If
too
small,
takes
a
long
/me
to
nd
square
root
If
make
too
large,
might
skip
over
answer
without
geGng
close
enough
In
general,
will
take
x/step
/mes
through
code
to
nd
solu/on
Need
a
more
ecient
way
to
do
this
Bisec&on
search
We
know
that
the
square
root
of
x
lies
between
0
and
x,
from
mathema&cs
Rather
than
exhaus&vely
trying
things
star&ng
at
0,
suppose
instead
we
pick
a
number
in
the
middle
of
this
range
0
x
g
If
we
are
lucky,
this
answer
is
close
enough
Bisec&on
search
If
not
close
enough,
is
guess
too
big
or
too
small?
If
g**2
>
x,
then
know
g
is
too
big;
but
now
search
0
x
new
g
And
if
this
new
g
is,
for
example,
g**2
<
x,
then
know
too
small;
so
now
search
0
x
new
g
next
g
At
each
stage,
reduce
range
of
values
to
search
by
half
Example
of
square
root
x = 25!
epsilon = 0.01!
numGuesses = 0!
low = 0.0!
high = x!
ans = (high + low)/2.0!
while abs(ans**2 - x) >= epsilon:!
print('low = ' + str(low) + ' high = ' + str(high) + ' ans = ' + str(ans))!
numGuesses += 1!
if ans**2 < x:!
low = ans!
else:!
high = ans!
ans = (high + low)/2.0!
print('numGuesses = ' + str(numGuesses))!
print(str(ans) + ' is close to square root of ' + str(x))!
Some
observa&ons
Bisec&on
search
radically
reduces
computa&on
&me
being
smart
about
genera&ng
guesses
is
important
Should
work
well
on
problems
with
ordering
property
value
of
func&on
being
solved
varies
monotonically
with
input
value
Here
func&on
is
g**2;
which
grows
as
g
grows
Newton-Raphson
General
approxima4on
algorithm
to
nd
roots
of
a
polynomial
in
one
variable
p(x)
=
anxn
+
an-1xn-1
+
+
a1x
+
a0
Want
to
nd
r
such
that
p(r)
=
0
For
example,
to
nd
the
square
root
of
24,
nd
the
root
of
p(x)
=
x2
24
Newton
showed
that
if
g
is
an
approxima4on
to
the
root,
then
g
p(g)/p(g)
is
a
beNer
approxima4on;
where
p
is
deriva4ve
of
p
Newton-Raphson
Simple
case:
cx2
+
k
First
deriva4ve:
2cx
So
if
polynomial
is
x2
+
k,
then
deriva4ve
is
2x
Newton-Raphson
says
given
a
guess
g
for
root,
a
beNer
guess
is
g
(g2
k)/2g
Newton-Raphson
This
gives
us
another
way
of
genera4ng
guesses,
which
we
can
check;
very
ecient
epsilon = 0.01!
y = 24.0!
guess = y/2.0!
!
while abs(guess*guess - y) >= epsilon:!
guess = guess - (((guess**2) - y)/(2*guess))!
print('Square root of ' + str(y) + ' is about '
+ str(guess))!
Itera4ve
algorithms
Guess
and
check
methods
build
on
reusing
same
code
Use
a
looping
construct
to
generate
guesses,
then
check
and
con4nue
Genera4ng
guesses
Exhaus4ve
enumera4on
Bisec4on
search
Newton-Raphson
(for
root
nding)