字幕表 動画を再生する
(train whistle)
- Hello and welcome to what will undoubtedly be
the longest video you've ever watched about binary numbers.
So why am I making this challenge here?
So I made a coding challenge number 117 called
the Seven Segment Display and what I was doing
was creating a visual, a JavaScript, HTML, canvas version
of the Seven Segment Display and to do that,
I had some weird code in there.
Val >> shift & 1
and that code, that code right up there
made no sense to anybody and I tried to explain it
but I got a lot of comments saying I didn't get
what this was so this is bit shipping and bit masking.
So before I can even get into that, I thought let's take
a deep breath and let's just enjoy and go back,
backwards in a time days of yore
when we didn't have anything but binary numbers
and we had to program everything in binary,
I don't know, this never happened for me
but I can imagine there was a time when this really happened
so this is a coding challenge where I will explain
what binary numbers are and then I will create a sketch,
p5.js sketch in JavaScript that converts
a binary number to a decimal number.
Okay so maybe you're even asking right now
what is a binary number, what is a decimal number?
So before I can even answer that,
we have to talk about this idea of base.
Base is
a term that refers to the number of possibilities
in a counting system, in a number system.
So base 2 or binary, there are only two possibilities,
a zero or a one.
Base 10,
ten, dec, deca,
or decimal has 10 possibilities, zero through nine.
There are other well-known numbering systems
that get used often, probably the one you see
in computing the most is base 16 or hexadecimal
and this actually has 16 possible digits,
zero through nine and also A through F
so when you see something like this in CSS
like FF
00
FF,
this is hexadecimal in coding.
This FF in decimal
is 255,
this 00 in decimal is zero,
this FF is 255 so this is the color,
this is a representation of the color red of 255,
zero of green and blue 255 so anyway,
so this kind of encoding of information exists
and by the way in my seven segment display,
there were hexadecimal representations
of what should be displayed on the seven segment display.
Okay so hexadecimal is interesting,
I'm not going to do hexadecimal conversion in this video
but you know, it's important to realize,
these are maybe something that you see,
I think base 8 is used for some file systems
but you can make up anything.
If you have base 4, you just have four possibilities,
maybe zero, one, two or three.
And when I say possibilities, this defines how you count.
And by the way, historically there are all sorts
of alternative ways of counting.
I believe, I was looking, Aztecs used maybe units of zero
then 20, then 40, then 800, then 8000
and instead of digits, they were actually drawings
of what, so anyway, so you can look that up,
somebody will make a nice explainer YouTube video
of counting systems but if we have base 2,
this means there are only two possibilities.
Let's use base 10 decimal 'cause we understand that.
10 fingers, 10 toes, that's why base 10 is the convention.
Zero, one, two, three, four, five, six, seven, eight, nine,
10, 11, 12, right 'cause once we get to nine,
we've run out of possibilities in a single digit
so we switch to zero and then the next digit over,
the tens unit becomes a one.
This is what kids learn in elementary school
in counting in groups of 10, hundreds units, et cetera.
All right but if I were doing this in binary,
I would say zero, then I would say one
and then I have run out of digits,
I have no more digits left, so I have to say one zero
and then one one and then, uh oh, one zero, zero,
then one zero one,
one one one, I'm totally,
this is the worst drawing ever,
and then one zero zero zero, did I get that right?
No, I totally did not.
One zero zero, one zero one, one one zero,
then one one one and then one zero zero zero.
Oh this is hard.
Okay let me match up some things for you.
So something that's really interesting here
is one matches up with one.
One zero matches up with two, one zero zero matches up
with four, five, six, seven, one zero zero zero
matches up with eight.
Notice that when there is only the leading digit one
and everything else is a zero, there's a pattern here.
One,
two,
four,
eight, maybe now you could imagine
what one zero zero zero zero is going to be.
How about
16?
Oops, sorry, 16, I should put that over here.
One, two, four, eight, 16.
These numbers are doubling so in fact,
each one of these digits in binary represents
not the tens, the twos.
So with a one, this is actually one,
this is actually two to the zero power.
Two, this is two to the one power.
This is two squared, two to the third power,
we're doubling so this is by the way
the algorithm that I need to write in my code
to convert from binary representation
to decimal representation.
Are you ready to do that?
I'm ready.
So one thing I want to show you first
is you can can actually, you don't need
to write your own algorithm to do this conversion,
this is built in to the way that computers work
and actually JavaScript has several helper functions
that'll do this for you. I think if I say for example,
=0b, if I have a variable that's =0b, I can put any encoding
so what if I put one one one one one one one one,
now actually the value of, that's actually 255.
So this is, I can actually hard code
a number in binary by saying 0b.
I can also use this parseInt function
so if I say parseInt and give it a string like 255,
just converts it, the string, to a number.
But I could do things like say parseInt
one one zero and then give it a radix or,
that's another word for base, and say what is the value,
the integer value, the decimal integer value
of one one zero in base 2, right, it's six.
If it were base 10, obviously it's 110.
So this will actually be done for you just through
that parseInt function but let's go and actually write
our own algorithm for this, yes, there is a bell ringing.
(bell ringing) And let's go to the web editor.
So let's just assume for the sake of argument
that the binary numbers that I want to work with
are going to be strings.
So I am going to make a number and I'm going to make it
a binary number and there's a thing about
when you have 8 bits, that's kind of important here,
right, each one of these is referred to as a bit,
each spot in a binary number is a bit.
When you have eight of them, that's a byte.
And so this has to do with how things are stored
in the computer's memory, right, everything ultimately
in the depths of your computer is stored in binary format
and the amount of space it takes up is the number of bytes
or kilobytes or gigabytes, et cetera, terabytes.
But I'm going to waste a lot of space and encode
my binary number as a string so let's just say,
let's just try something really simple
like one zero zero and we know that should be four, right?
Zero one one zero, no that's not four.
Yeah it is four, (chuckles) I lost my mind
for a second there, right?
This is zero, this is one, this is two, this is three,
this is four but we should, yeah, if we do this right,
we'll get four.
Okay now I want to write a function, I'm going to call it
bin, binaryToDecimal, it'll take in any arbitrary value
which is a string and we could make this much more generic.
By the way, as a challenge to you, what if you made
a function like this which is just number convertor,
it takes a number and two base, a base and a second base.
So here's the number in a given base,
give it back to me in another base.
It'll be generic, that's a challenge for you to do
now or later or whenever you want.
Okay, so the thing that I need to do is I need
to loop through
the...
Sorry, i = 0, i < val.length so if it's a string,
I'm going to loop through the string one character at a time.
So for each character, the way to convert it
is to add up all of the twos so for example,
one zero one is five because it is one zero zero
plus zero zero one is one zero one and this is four
and this is one so one zero one is five.
So if I just start here and take the first digit
multiplied by two and take the second digit
multiplied by, sorry multiplied by one,
the second digit multiplied by two,
the third digit multiplied by four,
add all those things together and by the way,
it's not just one two four, it's two to the zero,
two to the one, two to the two, two to the three.
So it's the exponent that's counting up.
So I'm going to say sum += pow,
now I need to get this value.
So I need to get the zero or the one so I'm going to say
the bit =
val.charAt(i).
Now here's the thing, hmm, hmm.
This is an interesting question here.
What is i when it starts at zero?
i is actually a string representation,
this is the zero index so even though I want
to do the conversion by starting over here,
I'm actually over here so I actually want to get
to the end of the, I want to start from the end
of the array, or not the array, the end of the string
and a quick way that I can do that is by saying
val.,
val.length-i-1,
right, if there are three digits,
I have
two one zero, not zero one two, two one zero.
So three minus i minus one.
So sum = pow(2, bit)
and I need to make this a number,
I'll just use parseInt 'cause it's a string
and then let's just say console.log(sum)
and I think we're done sort of (chuckles).
Console.log(sum), let's see,
let's do binary,
binaryToDecimal(val) and actually so this should return
a num, sorry,
and oh, there we go, four.
Let's test some other ones out.
Let's add another one.
Six.
Let's try one zero zero, this is a byte, right,
if all the ones are on in a byte, right,
everything is on, eight bits is a byte
and everything is a one, what do we get?
Okay I need one more.
Wait, what's going on?
Something is wrong.
No, this isn't right, I've made a mistake.
This code is not correct at all (chuckles).
So remember, I am each digit represents a one,
a two, a four, two to the (i)th power,
I actually even said that somewhere,
sometime earlier I said two to the (i)th power,
maybe only in my head.
So what I'm actually doing is taking that bit
and multiplying it.
Now of course it's a string so I have to convert it,
the string value.
Now this is what I'm looking to do and now
255, there we go, boy I had, somehow I was getting
some right answers by accident.
So that should be four.
This should be five, yeah.
Whoops, we can't have twos there (chuckles).
That should be 18.
So I should probably write some error handling, right,
because actually, this would actually work
if I put a three in there, it's going to give me a number
but it makes no sense at all.
So and once again, what I wanted to show
was that eight bits all on gives me
255.
And in fact, this is why we see again the range,
you can store 256 possibilities in a single byte,
a byte being eight bits, 256 in decimal
or two digits in hexadecimal.
I'm getting some messages from the chat
saying that maybe it would be more intuitive
to run the loop backwards.
So yes, but then I have, so it's six of one,
half dozen of the other as far as I'm concerned
because I either have to invert it here
or I have to invert it here so I don't know
which would be more, I mean I could have a counter
so you know I could do this, counter = 0
and I could run the loop backwards and then increase
the counter but I don't know, I'm going to stick
with what I have, all right, now, I said this was going to
be along one and I'm going to let it just be a long one.
You want to stick around and keep watching?
You can go do something else
but what I'm going to do is now make this interactive.
So I want to make something where I can actually click here
and I can turn on and off bits and see the conversion live.
So let's figure out how we're going to do that.
So I think I want to use some object oriented programming
and I am going to make a class.
I'm going to add another JavaScript file called bit.js
and I am going to make a bit class
and the bit class is going to have a,
and let me take off this auto refresh for right now,
it's going to have an X.
It's going to have an X and a Y
and a width, like a size, maybe I'll make it a circle
so it's going to have a diameter.
I'll use a circle to represent each bit
and then it's going to have a state,
right, it's state is going to be on or off.
Then I'm going to have a show function or render
I could call it where I'm going to say a stroke 255,
let's make the outline white and should it be,
I can never figure this out, is black on, white on,
I don't know, maybe I should make it red and blue,
we'll figure it out, we'll see how it looks.
So I'm going to say draw an ellipse
at this.x,
this.y, this.diameter
and
its fill is going to be 255 times this.state.
So in this case, it would be white if it's on.
So what I want to do now is make an array.
And let's just use eight.
We'll do a byte so I can call this a byte,
oh that's probably a bad word for me to use
'cause maybe that's reserved somewhere in JavaScript
but let's say i = 0; i < 8; i ++
and let's make
a bit = new Bit(i, so let's say I want to fit
all eight across in my, and I could use dom elements
or something that's going to be easier to interact with
but I'm just going to draw them as circles.
So I am going to say, I need to calculate a width
which is the width of the canvas divided by
eight.
So I'm going to say its x value is i * width,
its y value will be 50
and its diameter will be w
and I'm going to say byte[i]
= that bit
and I guess I don't need a separate variable here,
I'll just do this.
And then I want to say here,
I want to say byte[i].show.
So what do we got?
Oh, let me turn back on auto refresh
and I've got some errors.
Show is undefined.
I see a show function.
Oh wait, whoops, I put these in the wrong place.
The creation of them has to be in setup
and
this should go in draw, ah, no, stop, don't, ah.
All right, bit is not defined, oh of course,
I forgot that if I'm adding another JavaScript class,
I need to make sure I reference it from my HTML file
and now we're seeing and if all of them have a state
of on, hmm, I'm not seeing anything, so let's see,
oh, I've got to pass in the arguments, x,y,d.
So right now I want to set the arguments
based on this, there we go, there they are,
there's all my bits and maybe I want to offset them
a little bit.
And maybe I actually want this to be,
their diameter to be, have a little buffer in it.
Whoops.
There we go, so this is looking nice.
There are my bits, thank you very much,
oh I'm excited about this, this is going to be good.
And now if I take this state and state zero,
there we go, so now let's make this state,
let's actually also initialize the state,
I'm just going to write that in a separate,
I'm going to set state and I'm going to actually say
num.charAt(i).
So I'm going to use the character,
sorry I'm going to use the individual character there
to set the state of the particular bit.
Now, set state is not a function 'cause I need to add that
in here and I'm going to say setState(state)
and I'm going to say this.state = and I'll add parseInt
in here just to make sure it's a number
and now,
what's going on?
Set state is not a function, oh byte is not, of course,
byte[i].setState, there we go.
So now,
as I change values in here,
it turns those bits on and off.
Okay, we're gettin' somewhere.
Now what I want to do is I'm going to add a
decimal, I'm going to say decimalP,
decimalP = createP,
(vocalizing)
What is, what am I doing?
createP and then in the draw loop and it's silly
that I have a draw loop here, I don't need to continue
to draw but that's something that we can revise later.
I'm going to say, where's that function binaryToDecimal?
binaryToDecimal, I'm going to say...
decimalP.html(binaryToDecimal(num)
and so now we should see it says undefined,
ooh, oh, 'cause it's console logging it.
I want to return sum, okay 182, now you can barely see that
so let me go to my CSS for a second and add a color
and guess what?
I'm going to use hexadecimal.
Will it actually do it?
No I can use three F's 'cause it'll but let's use six
to do RGB and let's also make the font size much bigger.
Okay so now and let's actually make this a,
it's got this extra, 'cause it's a paragraph element,
actually this is so silly but I'm going to make it a div
just so it shows up up here, okay, so now,
this is not interactive but I can do this
and it does feel, it does look inverted, right,
this really looks like on, off, on, on,
the way that I've kind of drawn this.
Somehow the black color looks like I've turned it on
so I could probably make the background much darker.
If I made the background 51, yeah, so maybe this,
I still, I don't know, it's so confusing.
What if I made?
I don't know which is which, you tell me,
my visual design skills are kind of a disaster
but if I go back to this, but anyway,
whichever way I think it is, I could actually just say
255 minus this and now, right, now it is colored black
when it is on and I could say one zero one zero
one zero zero one, we can see 169, okay.
Should I make this interactive?
I mean I've gone on for way too long already.
Let's make, 'cause I need to make this interactive,
do you know why?
Because the whole point of doing this was
to talk about bit shifting and bit masking,
I'm going to get to that, that I'll do in a separate video.
Let's make this interactive.
So what do I need here?
I need some sort of function to see if this bit contains
a point so if, so what I need to do is calculate
the distance between this point and its X and Y
and then if the distance is less than the radius
which is the diameter divided by two
and it's this dot diameter.
And I'm going to call this toggle, I'm actually just going to,
I could return this, I'm going to make this
the toggle function, then I'm going to say
this.state =, now if the state is a zero,
I want it to be a one, if it's a one,
I want it to be a zero.
What's a nice way of doing that?
I mean I could write an if statement.
People are giving me great suggestions like +1 module
is 2 to the power of -1, I think I'm just going to admit
to myself that really what I meant was for this
to be true or false (chuckling) so I'm going to,
the state's going to be false and when I say set state,
I'm going to do parseBoolean, is that a function in JavaScript?
Let's see if it is and then I can say not this.state.
parseBoolean is not defined (chuckling).
There's no parseBoolean?
What if I do Boolean?
Ah, there we go, okay so boolean is a function I guess
that will convert that to this
and then here, what I want to do is I could just say
if this.state fill(0) and of course this is rather awkward
but I don't care, this is how I like to write code,
there we go, mm, mm this is no good.
Oh you know what?
Those are strings.
So this needs actually to say parseInt.
There we go, okay, we're back, we're back baby.
Okay, now this, boy, there's lots of things
you can improve, right?
All right now what I can do is make these interactive.
So I can now add the mouse pressed function
and I can just say for and I can loop through again.
Once again, I can loop through
and this should really be byte.length.
I can do this and I can loop through all of them
and I can say toggle, oops, no, and I can just call toggle
with the mouse coordinates.
So it's toggling, the toggling is working
but it's not updated.
Ooh, why is it not updating?
Because, oh, I am converting the string.
My function converts a string so I could do something
like make that, I could make the decimal version
of the number out of the array of bit objects
but I think what might actually work nicely here
is for to make the string out of it
so what if what I do now is I say in here,
I'm going to say, I'm just going to use that same variable,
num = an empty string and then I'm going to say
num +=...
Oh this is in setup, sorry, in draw,
+=, now I want to have a zero or a one
because if I say this dots, byte[i].state.
So this is where I have to use
but I have to embrace the ternary operator,
it's something that I have never natively really understood.
It's never fit into my brain but this thing
called ternary operator and it looks like this.
The condition and if the condition is true,
this is the result, if it's false, this is the result.
We can make this happen right now.
We can use that ternary operator.
The condition is actually just byte[i].state.
Then I need the question mark and this is so nice,
I just need to have if it's true a one
or a zero, it's false.
Oh I need to say
recreate that string, whoa, look, it's going crazy.
There we go.
Look at this.
Now, ooh so lovely, let's go, we did it.
(bell ringing)
Everybody, we did it, I made a binary thing
that you can click on bits and convert it
to a binary number.
Now here's the thing, oh boy, you,
the creative person watching, if you made it
to the end of this video, wow, you really are something.
Thank you, I can't believe it
because this was ridiculously long winded
to just explain binary numbers
but you now have the opportunity
to make something creative here.
What if you made, you could make a clock
that displays the time in binary.
Maybe you could actually also show the hexadecimal value.
You could actually make this a form content editable
that you can convert backwards, how you convert,
this is a thought experiment for you,
I can come back and do another video,
but how do you convert not form binary to decimal,
how would you convert from decimal to binary?
I'll give you a hint, it has to do with division
and the remainder, I think, so there's so many things
you could do, you can make a more interactive version,
you can make a counter that's sort of...
Ooh this would be fun to have this count up in binary.
That's kind of like the clock.
You'll be in color, other ways of visualizing it,
you'll come up with something, I know you will.
You always do.
Thank you so much for watching this coding challenge
and I will, remember at the beginning when I said
the whole point of this was talking about bit shifting
and bit masking, I will come back and I will do that.
So that will be in a separate challenge.
I'm going to add some buttons for shifting and masking.
(train whistle)
(upbeat music)