Lecture 3: String Manipulation, Guess and Check, Approximations, Bisection
MIT OpenCourseWare continue to offer high quality educational resources for free. To make a
donation or view additional materials from hundreds of MIT courses, visit MIT
OpenCourseWare at ocw.mit.edu.
ANA BELL: All right everyone, let’s get started. So good afternoon. So this is the 3rd lecture of 6.0001 and
600. As always, please download slides and code to follow along.
So a quick recap of what we did last time. Last time, we talked about strings as a new object
type, as sequences of characters. And then we introduced two new concepts that allowed us
to write slightly more complicated programs.
So we introduced branching, with these keywords, if, elif, else. And branching allowed us to
write programs that, us, as programmers, could introduce decisions into our programs. And
then we introduced two different kinds of loops, while loops and for loops. And those also
added a little bit of complexity to our programs.
Today, we’re going to talk a little bit more about strings. So we’re going to see a couple of
more operations that you can do on strings and string objects. And then we’re going to talk
about three different algorithms, a guess and check algorithm, an approximate solution
algorithm, and a bisection method algorithm.
So let’s dive right in. We’ll talk a little bit about strings, first. So strings, we thought of them as
sequences of characters, case sensitive, as we saw in programs we wrote last lecture. And
strings are objects. And we can do all of these operations on string objects, like test if they’re
equal, less than, greater than, and so on.
It turns out, we can do more than just concatenate two strings together or do these little tests
on them. So we’re going to start introducing the idea of a function or a procedure. And we’re
going to see more about functions and how you can write your own functions next lecture.
But for today, you can think of a function as sort of a procedure that does something for you.
Someone already wrote this. So the first one we’re going to look at is a pretty popular function.
And when applied on a string, this function, called len, will tell you the length of a string. So
that’s going to tell you how many characters are in the string. And characters are going to be
that’s going to tell you how many characters are in the string. And characters are going to be
letters, digits, special characters, spaces, and so on. So it’s just going to count how many
characters are in a string.
So if I have the string s is equal to “abc”– remember a string is in quotation marks– then, if I
do this, if I write this expression, len s, here, since it’s an expression, it has a value. So it
evaluates to a certain value. And by definition, it’s going to tell me what the length of the string,
which is 3 characters long.
Another thing that we can do on strings is, since they’re a sequence of characters, I might
want to get what character is at a certain position. So we do this using this fancy word called
indexing. But pretty much what indexing into a string means is you’re going to tell Python, I
want to know the character, at this certain position or at this certain index, inside my sting.
So once again, let’s use this string, s is equal to “abc.” And let’s index into it. So in computer
science, we start from 0, counting by convention. Notice, we had a problem set 0 in this class.
Python is no different.
So in Python, you start indexing at position 0. Or you start indexing at 0. So the first character,
in your string, we say is at position 0 or at index 0. The next character in the string is at index
1. And the next character in the string is at index 2.
In Python, it turns out, you can also use negative numbers to index. And if you index into the
string with negative 1, for example, that means that you want the last character in the string.
So the last character in your string is always going to be at position negative 1, the second-to-
last character is at negative 2, third-to-last character is at negative 3, and so on and so on.
So the way you index into a string is with these square brackets, here. And this is the notation.
So if I want the character at position 0 or at index 0, I say s, which is the string I want to index
into. And then, inside the square brackets, I say what index I want.
So s at index 0 is going to be the value “a.” s at index 1 is going to be the value “b,” and so on
and so on. And we can also do negative indexing, as well.
I added this in here. If you do try to index into a string beyond the limits of the string– and we
can even try this out, just to show you that it’s not the end of the world if we do that. If we have
s is equal to “abc,” and we have s at position 20, for example, obviously, my string is only
length 3, so what’s at position 20?
I get an error. I call this angry text, here, in Python. But really, the most relevant thing to note
is these last couple of lines here. This tells you what line is problematic. So s at position 20 has
an issue. And this last line here tells me what actual error I have. So it’s an index error, which
means I’m trying to index too far into the string, because it only has three characters.
So it’s nice to be able to get a single character out of my string. But sometimes, I might want to
get a substring. So I want to start at the first character and go halfway into the string, or I want
to take a few characters in between, or I want to skip every other letter or something like that
in my string.
So if I want to do this slightly more complicated interaction with strings, we call that slicing,
slicing into a string. And this notation here should seem a little bit familiar, because we saw it
last lecture when we did it with range.
We had a start, stop, and a step. The notation was a little bit different, because, in range, we
had open-close parentheses and commas in between. But except for that, this sort of works
the same.
The start is the index, starting from 0, from where you want to slice into this string. The stop is
the stop index. So you’re going to go up until stop minus 1 and take that index. And then the
step is how many letters you wish to take.
So this is the full notation here. But sometimes, you can not give it a third sort of number in
here. So if you only give it two numbers, then, to Python, that represents just the start and the
stop. And by default, step is going to be 1.
And there’s a lot of other things you can do with strings. You can omit numbers and just leave
colons in Python. By definition, the way that whoever wrote slicing had decided, if you omit
numbers, then it’s going to be equivalent to these things here.
So we slice using square brackets, just like indexing. Except now, we can give it two numbers.
So with this string, s, if we slice into the string s, we start from index 3 and go up until index 6.
So if we have abcdefgh, this is position 0, 1, 2, 3, 4, 5, 6, 7.
And you just count. So s, starting from 3 and going till 6, is going to start here, 3. So it’s going
to come up with– sorry d. And then we’re going to take e. And then we’re going to take f. And
since we’re going until stop minus 1, we’re not going to take g. Because this is position 6, and
we’re going until 6 minus 1.
The next one here, 3, 6, 2 is going every other one. So we start at 3, and then we skip every
other one, so we go d but not e, and then f, and then stop.
If you do s and then nothing inside except colons, notice that you’re going to have s, and then
nothing, and then colon, nothing, colon, nothing. So nothing for start, nothing for stop, nothing
for step. And that’s just going to value it to the string, itself. It’s the same as 0 to the length s
going every step.
This one might actually be useful. It reverses the string automatically for you. So with this one
little line here, you can get the inverse of your string. And that’s equivalent to that. So the
minus 1 represents starting from the end and going back every letter. And then this one’s a
little bit more complicated but also not too bad.
So as we’re doing these string slices, again, if you’re unsure what something does, just type it
into Spider. And you might be surprised. You might not be. But it’s a good way to check
yourself, to make sure you’re understanding what’s happening.
One thing I want to mention, and it’s good to keep this in the back of your mind. We’re going to
come back to this as we start talking about slightly more complicated object types. But strings
are immutable. So just keep this word in the back of your mind as we go through this class.
And what I mean by this is that an actual string object, once it’s created, cannot be modified.
This might not mean anything right now. But let me just draw a little something. Let’s say I
have this string, s is equal to hello.
Remember, in the first lecture, we drew a diagram sort of like this. This is my memory. I have
this object “hello.” And this object, “hello” is bound to this variable s. So now I can access the
object “hello” using this variable s.
Now you might think, well, since I could index into a string, I might be able to just say
something like, s at position 0 is equal to y. And that will just change the little h into a y, and I’ll
have a new object.
Well strings are immutable, which means, in Python, you’re not actually allowed to do this. And
it gives you an error if you do try to do that. If you want the variable s to point to the string, YE-
L-L-O, you could just say s is equal to Y-E-L-L-O.
Or you could do string operations like this. And this takes the y and it concatenates it to the
string s, all of the elements starting from position 1, which is e, l, l, o. So this makes Y-E-L-L-O.
Now internally, what happens when I write this line is Python says, OK, I’m going to break my
bond with this original object “hello.” I’m going to bind my string variable s to the new object
“yello.” and this other, old object still is in memory somewhere. But it’s an entirely different
object that I’ve created here.
Again, it might not mean anything right now, but just keep this in the back of your mind, strings
are immutable.
So the next thing I want to talk about is a little bit of recap on for loops. And we’re going to see
how we can apply for loops, very easily, to write very nice, readable code when dealing with
strings.
So remember that for loops had a loop variable. My loop variable being this var, here, in this
particular case. It can be anything you want. And this variable, in this particular case, iterates
over this sequence of numbers, 0, 1, 2, 3, 4.
So the very first time through the loop, var has a value of 0. It does the expressions in the
loop. As soon as they’re done, var takes the value 1. It does all the expressions in the loop.
And then var takes the value 2, and it does that all the way up until 0, 1, 2. And the last time it
goes around is with var is equal to 3.
And remember, we said that we can customize our range in order to start from a custom value
to end at a different value and to skip certain numbers.
So, so far, we’ve only been using for loops over a sequence of numbers. But actually, for loops
are a lot more powerful than that. You can use them to iterate over any sequence of values
not just numbers but also strings.
So here are two pieces of code, this one and this one here. These two pieces of code both do
the exact same thing. To me, possibly to you, this one looks a lot more readable than this one,
just at a first glance.
If I were to read this one, just using the keywords and variables here, it would sound like
broken English. But you could decipher what I’m trying to say. For a char in a string s, if the
char is equal to “i” or a char is equal to “u,” print “There is an i or a u.”
char is equal to “i” or a char is equal to “u,” print “There is an i or a u.”
It sounds weird, but you could probably tell what I was trying to do here. Whereas up here, it’s
a little more complicated to tell what I’m doing. You have to sort of think about it a little bit.
For some index in this range of numbers, 0 through the length of the string s, if s, at position
index, is an “i” or s at position index is a “u” print, “There is an i or a u.” Both of these codes
just go through the string s. And if it encounters a letter that’s an i or a u, it’s just going to print
out this string here.
But this bottom one is a lot more pythonic. It’s an actual word created by the Python
community. And it just looks pretty, right? You can tell what this code’s supposed to do.
Whereas this one is a little bit harder to decipher.
So that’s sort of an illustration of a for loop over a sequence of characters. So char is going to
be a loop variable, still. And the loop variable, instead of iterating over a set of numbers, it’s
going to iterate over every character in s, directly. And char is going to be a character. It’s
going to be a letter.
So here’s a more complicated example. I wrote this code a couple of years ago. And it was my
attempt at creating robot cheerleaders , because I needed some motivation. And then I
googled, last night, “robot cheerleaders,” and was not disappointed. Created this GIF. It looks
pretty cool. And it looks like they kind of stole my idea. But that’s fine.
So let’s look at what this code’s supposed to do. I’m going to run it. I’m going to run it, and
then we’ll go through it. All right, it prints out, “I will cheer for you! Enter a word.”
You know what, I like robots, so I’ll put in “ROBOTS.” How enthusiastic am I about robots?
Let’s say 6. So what this is going to print is– it’s a cheerleader, right? “Give me an r, r.” “Give
me an o, o.” “Give me a b, b,” and so on and so on.
“What does that spell? ROBOTS.” And it’s going to print it 6 times, because I’m 6 out of 10
enthusiastic about robots. So that’s pretty much what that code’s supposed to do. And you can
write it using what we’ve learned so far.
Now let’s go through it a little bit. And I’m going to show you just how easy it is to convert this
code using a for loop over characters. Right now, what it does is it asks the user for input, so a
word and a number.
And then it does this thing, here, right? First, it uses a while loop. And second, it uses indexing.
And what tips you off that it’s using indexing is it’s using the square bracket, here, into the
word.
And obviously, it’s using a while loop. And it has to first create a counter, initialize it. And then,
down here, it’s going to increment it inside the while loop. If you remember, that’s sort of what
we need to do for while loops.
So it’s going to start at 0, and it’s just basically going to go through index i is equal to 0, 1, 2, 3
4, which is going to go all the way to the end of the word, whatever the user typed in, in this
case “ROBOTS.” It’s going to get the character at that position. word at position i is going to be
a character.
This line here is just for the cheerleading to make sense. It’s just to take care of letters that
make sense to use an, right? So give me a b, give me an b. So give me an b does not make
sense, right? So that’s just taking care of that.
And I’m using this in keyword to check whether the character– so the character, r, for
example, in robots– is inside an letters. And an letters I’ve defined up here, which is these are
all the letters that make sense to put an an before the letter. So give me an r for example,
here, on the right.
And so if it makes sense to use an before the letter, use that, and otherwise use just an a. And
after I’m done, I say, “What does that spell?” And then it’s just a for loop that goes times many
times and prints out the word and the exclamation mark.
So this code might have been a little bit more intuitive if I rewrote it or if I’d originally written it
with a for loop. So this part here, the while loop and indexing and creating my original counter,
we can get rid of that.
And we can replace it with this, for char in word. I’m originally using char, so I can use char as
my loop variable again. And simply, I’m just going to iterate over the word, itself.
So now, instead of having this mess here, I have a one-liner that says, for every character in
my word, do all this stuff here. So that remains the same. And then I don’t even need to
increment a counter variable, because I’m not using while loops anymore. I’m just using a for
loop.
So the code becomes– delete that– for char in word. And then delete that. And that does the
exact same thing. And it’s a lot more readable.
So this was our toolbox at the beginning of this course. We are two and half, I guess, lectures
in. These are the things we’ve added to it. We know integer, floats, Booleans. We know a bit of
string manipulation, math operations. We added, recently, these conditionals and branching to
write slightly more interesting programs.
And now we have loops, for and while loops to add interesting and more complicated
programs. So with these, the second part of this lecture is going to be looking at three different
algorithms. That’s the sort of computer science part of this class, Introduction to Computer
Science and Programming using Python.
Don’t let the word algorithm scare you. They’re not that complicated. You just have to sort of
think a little bit about them. And you’ll be able to get them.
So we’re going to look at three algorithms, all in the context of solving one problem, which is
finding the cube root. The first algorithm is guess and check, then we’re going to look at an
approximation algorithm, and then a bisection search.
So the first is the guess and check method. You might have done this, in math, in high school.
The guess and check method is also sometimes called exhaustive enumeration. And you’ll see
why.
So given a problem, let’s say, find the cube root of a number, let’s say you can guess a
starting value for a solution. The guess and check method works if you’re able to check if your
solution is correct.
So if your guess is originally 0, you can say, is 0 cubed equal to the cube of whatever I’m
trying to find the cube root of? So if I’m trying to find the cube root of 8, is 0 cubed equal to 8?
No. So the solution is not correct.
If it’s not correct, guess another value. Do it systematically until you find a solution or you’ve
guessed all the possible values, you’ve exhausted all of your search space.
So here’s a very simple guess and check code that finds the cube root of a number. So I’m
trying to find the cube root of 8. So my cube is 8. I’m going to have a for loop that says, I’m
going to start from 0. And I’m going to go all the way up to–
So I’m going to start from 0 and go all the way up to 8. For every one of these numbers, I’m
going to say, is my guess to the power of 3 equal to the cube 8? And if it is, I’m going to print
out this message.
Pretty simple, however, this code is not very user friendly, right? If the user wants to find the
cube root of 9, they’re not going to get any output, because we never print anything in the
case of the guess not being a perfect cube. or the cube not being a perfect cube.
So we can modify the code a little bit to add two extra features. The first is we’re going to be
able to deal with negative cubes, which is kind of cool.
And the second is we’re going to tell the user, if the cube is not a perfect cube, hey, this cube
is not a perfect cube. So we’re not going to silently just fail, because then the user has some
sort of feedback on their input.
So let’s step through this code. We have, first of all, a for loop just like before. And we’re going
to go through 0 to 8 in this case. We’re using the absolute value, because we might want to
find the cube root of negative numbers.
First thing we’re doing is doing this check here. Instead of guessing whether the guess to the
power of 3 is equal to the cube, we’re going to check if it’s greater or equal to, and we’re going
to do that for the following reason.
So if we’re trying to find the cube root of 8, for example, versus a cube root of 9– this is 8 and
this is 9– what is this code going to do? It’s going to first guess 0. 0 cubed is not greater or
equal to 8. 1 cubed is not greater or equal to 8.
2 cubed is greater or equal to 8, so here, once we’ve guessed 2, we’re going to break.
Because we found a number that works. And there’s no need to keep looking. Once we’ve
found the cubed root of this number 8, there’s no need to keep searching the remainder, 3, 4,
5, 6, 7, 8.
Sort of the same idea when we’re trying to find the cube root of 9. We’re going to start with 0.
0 to the power of 3 is less than 9. 1 to the power of 3 is less 9. 2 to the power of 3 is less than
9.
When we get to 3 to the power of 3, that’s going to be greater than 9. So this code tells us,
once we’ve picked a number that’s beyond the reasonable number of our cubed root, of our
once we’ve picked a number that’s beyond the reasonable number of our cubed root, of our
cube, the cubed root of our cube, then we should stop.
Because, again, it doesn’t make sense to keep searching. Because if 3 to the power of 3 is
already greater than 9, 4 to the power of 3 is also going to be greater than 9 and so on. So
once we break here, we either have guess being 2 or guess being 3 depending on what cube
we’re trying to find.
And if the guess to the power or 3 is not equal to the cube, then, obviously, the cube was not a
perfect cube. So that’s this case here, if we were looking at at the cube root of 9. And
otherwise, this part here just looks at whether we should make it a positive or a negative cube.
So if our original cube was less than 0, then, obviously, the cube root of a negative number is
going to be a negative number, and, otherwise, it’s just our guess.
So that’s the guess and check method, slightly more feature-rich program for guessing the
cube root. But that only tells us the cube root of perfect cubes and doesn’t really give us
anything else, any more information.
So sometimes, you might want to say, well, I don’t care that 9 is not a perfect cube, just give
me a close enough answer. So that’s where approximate solutions come in. So this is where
we’re OK with having a good enough solution.
So in order to do that, we’re going to start with a guess and then increment that guess by
some small value. Start from 0 and start incrementing by 0.001 and just go upwards from
there. And at some point, you might find a good enough solution.
In this program, we’re going to keep guessing as long as we’re not close enough. And close
enough is going to be given by this epsilon value in the program. So as long as the guess
cubed minus the cube– so how far away are we from the actual answer– is greater than some
epsilon, keep guessing, because the solution is not good enough.
But once this is less than epsilon, then we’ve reached a good enough solution. So two things
to note with approximate solutions. So you can get more accurate answers if your step size is
really, really small. If you’re incrementing by 0.0001, you’re going to get a really good
approximate solution, but your program will be a lot slower.
Same sort of idea with epsilon, you can change epsilon. If you change epsilon to be a bigger
epsilon, you’re sacrificing accuracy, but you’re going to reach a solution a lot faster.
So here’s the code for the approximate solution of a cube root. It might look intimidating, but,
look, almost half this code is just initializing variables. So we’re initializing, this is the cube we
want to find the cube root of. We pick an epsilon of this. We start with a guess of 0. We start
with an increment of 0.0001. And just for fun, let’s keep track of the number of guesses that it
takes us to get to the answer.
This is similar to the guess and check from before. It’s not similar. Well this part is similar to
the guess and check from before. So we’re going to take the guess to the power of 3 minus
the cube, right? So that’s how far away are we from the actual answer?
And we’re going to say, if that’s not good enough– so if we’re still greater than or equal to the
epsilon– then keep guessing. So we’re going to be stuck in this loop, where we keep guessing
values, until we’ve reached a guess that’s good enough, so until we’re less than epsilon.
And way we keep guessing is just with this line, right here, which says, increment my guess by
increment, and increment being this really small value. That make sense?
So I’m going to keep incrementing my guess by that small value. Before I go on, I’m going to
run the code. And we’re going to discover a small issue with it.
So with 27, we’re going to run it. Perfect, it took me 300 guesses. But 2.99999 is close to the
cube root of 27. We can find the cube root of this guy here. And it took me 20,000 guesses,
but I figured out that 200.99999, so 201, is close to the cube root of that large number.
I should have done this. This is going to be a giveaway, you guys. Sorry. Then we’re going to
have– let’s say I want to try cube of 10,000. So 10,000 is not a perfect cube. So we can run
the code. And with 8,120,601 I had already gotten an answer. But with 10,000, I’m not getting
an answer yet, right?
So I’m thinking that there might be something wrong. So I’m going to stop my code. So I just
hit Control C, because I feel like I’ve entered an infinite loop. And, in fact, I have. So what
ended up happening is this problem here.
So I’m going to draw something. According to the code, I’m going to start from 0, and I’m
going to increment my guesses, like that. With every little increment, I’m going to make a new
guess. I’m going to take that guess to the power of 3. I’m going to subtract the cube, and I’m
going to figure out if I’m less than epsilon.
This is the epsilon that I want to be in, this little bit here. So with every new guess, I might be,
maybe– so this is where I want to be, within this little boundary here. With every new guess, I
might be here.
With the next guess, over here, I might be here. When I make another guess, I might be here.
So I’m getting close to being within epsilon. But maybe with my next guess, I’m going to hop
over my epsilon and have made too big of a guess.
So just because of the way the numbers were chosen in this example, just to illustrate this,
using an increment of 0.01, a with finding the cube of 10,000 and epsilon of 0.1, it turns out
that, as I’m doing all these calculations, I’m going to skip over this perfect sort of epsilon
difference.
So first, I’m going to be too small. And then I’m going to be too large. And once I’ve become
too large or too far away from epsilon, the guesses I continue to make are just going to be
even farther away from epsilon. And I’m not going to get to my answer.
And that’s why I’ve reached an infinite loop in this code. All I’m doing in this code is checking
whether my guess cube minus cube is less than epsilon. The only thing I need to do here is
sort of add this little clause, here, that says, oh, by the way, also check that I’m less than cube.
Because this is just like we did in the very first program, when I’m checking 0, 1, 2, 3, 4, 5, 6,
7, 8, when I’m trying to find the cube root of 8. Once I’ve reached 8, I’m going to stop. And it’s
the same thing here.
So I just added this little clause that says, well, while I’m greater than or equal to epsilon and
I’m still less than the actual cube, just keep searching. But once I’ve reached the cube, then
stop searching.
And with 10,000, you can see that I failed to actually find– so that’s what this part, here, does.
It tells me I’ve failed to find the cube root with those particular parameters.
The last thing we’re going to look at is bisection search. And to illustrate this, I’m going to need
one volunteer. And you’re going to play a game with me in front of the whole class. And there
will be a prize. There go the hands. In the blue shirt, right there. Cool.
So the prize is going to be, once again, this. I promise I don’t have millions of these, Google
glasses. I also don’t work for Google. I just happened to get a couple.
So the game is this. I’m going to ask you to pick a number, a whole number, between 0 and
100. And I’m going to try to guess it. And you need to make it hard for me. And you need to
make it so hard for me that I cannot guess it within 10 guesses.
And if you can do that, if I cannot guess it within 10 guesses, you get this. And I’m going to
draw out what I do as we go along. So do you have your number? Yes?
AUDIENCE: Yeah.
ANA BELL: Perfect. Let me erase that. Actually, I should’ve probably kept that, because I’ll still use it.
There’s the numbers, 0 to 100. Is your number 50?
AUDIENCE: No.
ANA BELL: 50 Was my guess. So I’ve made one guess. Is your number higher or lower than 50?
AUDIENCE: Higher.
ANA BELL: Higher. Is your number– my next guess is going to be 75. And the reason I’m guessing 75 is
because– what’s your name?
AUDIENCE: Sophie.
ANA BELL: What’s that?
AUDIENCE: Sophie.
ANA BELL: Sophie. Sophie said, 50 was too low. So I immediately know that it cannot be any less than 50.
So I’ve already eliminated half of the numbers. So my next guess is 75. Is your number 75? Is
your number lower or higher?
AUDIENCE: Higher.
ANA BELL: Since it’s higher, I’m eliminating this half here. Is your number– so between 75 and 100. Oh,
boy, you’re putting me on the spot. What’s that?
AUDIENCE: 87.
ANA BELL: 87, thank you. 87?
AUDIENCE: No.
ANA BELL: Higher or lower?
AUDIENCE: Lower.
ANA BELL: Lower. So since it’s lower, I’m eliminating that half. Is your number 81? Higher or lower?
AUDIENCE: Lower.
ANA BELL: So she said, lower, so I’m eliminating that half. Is your number 78? Oh, boy, that’s really hard.
78, OK. Higher or lower?
AUDIENCE: Lower.
ANA BELL: Is your number 76?
AUDIENCE: Yeah.
ANA BELL: Yay. All right, perfect, 76 was the number. So how many guesses have I made? One, two,
three, four, five, six– I made six guesses. So I did get it under 10. But you know what? The
game was rigged. So you get the prize anyway, just because I rigged the game. Here you go.
Pass it down.
AUDIENCE: Thank you.
ANA BELL: Thank you. So notice, in bisection search, what I did was I eliminated half the search space
with every guess. I said, well, she said it’s higher or lower, so I definitely cannot be in the other
search space, right? If I was doing approximate solution or, in this case, guess and check, I
would be asking Sophie, is your number 0, 1, 2, 3, 4, and so on?
So with guess and check, it would have taken me 76 guesses to get to the number, whereas,
with this bisection search, that I just did, it only took me 6. Isn’t that cool?
So that means that the larger the space actually is, that I need to search, the better it is to use
bisection search, this bisection search method. So that’s basically what I’m illustrating here. So
we have our original search space. We’re going to choose a guess halfway, eliminate half of
the guesses. Then we’re going look in the remaining interval, eliminate half the guesses, and
so on and so on.
So then this is the code for bisection search. Also looks intimidating, but it’s not so bad. So
we’re initializing a bunch of stuff up here. The most important couple of things we’re initializing
are, first of all, this high and this low boundaries.
So with the guessing game, the low boundary was 0, and the high boundary was 100. When
we’re looking at the cube root, the low boundary is going to be 0, and the high boundary is
going to be just my cube, because a guess to the power of 3 cannot be any greater than cube.
And then, I’m just going to do the same procedure that I did with the guessing game, which is
I’m going to make my guess, be halfway in between. So with this guessing game, I had to sort
of choose, if there were four numbers in between, should I go higher or lower?
Well, when we’re doing by bisection search, here, we don’t care about that. We’re just going to
do floating point division, because we want decimal numbers. So I have a low boundary and a
high boundary. And I figured out my halfway point.
Then I have this while loop here. A while loop is similar to the approximation method, where,
as long as I don’t have a guest that’s good enough– so this, depicted by this greater or equal
to epsilon– as long as my guess is not good enough, I’m going to keep guessing. That’s what
this while loop is saying.
So if the guess to the power of 3 minus cube is not good enough, keep guessing. And the way
I keep guessing is this part, here, says, my guess was too low. So if my guess was too low, set
the low boundary to be the guess. Because I don’t care about all of the other numbers that are
much lower than me.
So set the low to be the guess. That’s what that line is doing. And otherwise, my guess was
too high. That’s what this else is doing. So set the high to be the guess, because I don’t care
about numbers any higher than my guess.
Once I have these new boundaries, I make another guess, again, halfway in between the new
boundary points. So essentially, I’m just halving my interval with every single guess. And that’s
what the while loop is doing. And then I print out the remaining part.
So notice the search space originally being N, we’re halving it with each guess. So the first
guess divides it by 2, the second guess divides it by 4, and so on. So by the time we get to the
k-th guess, N/2k, the k-th guess, let’s say that’s the actual answer we’re interested in. There’s
only one value in that little interval. And that’s the answer we want.
So 2 to the k is equal to N. And then how many guesses did we make? k is equal to log base 2
of N. So when we are playing the guessing game of 100, my end was 100. Log base 2 of 100
is 6.-something, I think.
So in fact, I could have said, if I don’t guess it within seven guesses, you would have won as
well. So that’s why the game was rigged. So the guess, notice, it converges on the order of log
base N instead of just linearly in terms of N. So that’s why it’s so powerful.
One last thing I want to mention is the code I showed only works for positive cubes. And that’s
because of the following. So I have this 0 and 1. Let’s say I’m trying to find the cube root of
0.5.
When I first set my initial boundaries, my low is this one, and my high is this one. But what’s
the cube root of 0.5? Is it within this boundary or is it outside this boundary?
AUDIENCE: Outside the boundary.
ANA BELL: I heard, outside. It’s like 0.7 something. So it’s out here. So with this particular code, I’m going
to be halving my interval in between those numbers, but I’ll never get to an answer. Because
the actual cube root of 0.5, or numbers less than 1, is going to be outside that boundary.
So there’s a small change you can make to the program, which will fix that. And that’s in the
code. I didn’t put it in, but it’s a very small change, a small if statement. So that’s it. All right,
thank you.
[APPLAUSE]
