"Hi, Amigo!"

"Hi, Bilaabo!"

"I want to tell you a little about different numbering systems."

"You've already heard that people use the decimal system. Here are the main facts of this system:

1) 10 digits are used to write numbers: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

2) The number 543 means 5 hundreds + 4 tens + 3 ones.

"This is equivalent to writing 5*100 + 4*10 + 3*1, which can be written as 5*102 + 4*101 + 3*100.

Note that thousands, hundreds, tens and ones are powers of the number 10.

1) One is 10 to the zeroth power.

2) Ten is 10 to the first power.

3) One hundred is 10 to the second power.

4) One thousand is 10 in the third power, etc.

"Yep. Got it."

"But now imagine that we only have 8 digits. Then we have the octal system. Here are its main facts:"

1) 8 digits are used to write numbers: 0, 1, 2, 3, 4, 5, 6, 7.

2) The number 5438 means 5*82+4*81+3*80. In other words, it's 5*64 + 4*8 + 3*1 = 320+32+3 = 320+32+3=35510

I wrote 8 and 10 as subscripts to indicate how many digits are used to represent the number.

"I think I get it. I think I could convert a number from the octal system to decimal. But I probably couldn't go the other way."

"It's not so difficult. Imagine you need to use several trucks to move a pile of sand. You have dump trucks, ordinary trucks, and very small trucks. But the trucks can't go if they're not full."

"How would you do it?"

"First, I would fill up dump trucks, since they're the biggest. Then, when I saw that there wasn't enough sand to fill the truck, I would switch to the smaller vehicles. And then the even smaller ones."

"It's actually very similar here. Let's try to convert the number 35510 back to octal."

"First, we divide it by 64 (82) and get 5 with a remainder of 35. This means that the first digit of our number is 5. Then we divide the remainder by 8 (81) and get 4 with a remainder of 3. Thus, we get the number 5438."

"By the way, you can also move in the other direction. After all, 5438 == 5*64+4*8+3 == ((5)*8+4)*8+3. Our octal "tens" and "hundreds" must be divided by 8. Hence, the remainder of division by 8 will be our octal digits."

"First, let's divide 355 by 8. We get 44 with a remainder of 3. That is, 355=44*8+3. And 44 can be represented as 5*8+4. Thus, 355= (5*8+4)*8+3; Here are our digits: 5, 4, 3. The number we're looking for is 5438."

"I think I get it, but I'll need to practice a little to understand everything all the way."

"Programming often involves using numbers with different bases (i.e. the number of digits used in the numbering system). The most popular are 2, 8, 10, 16, and 64."

"But why is this necessary? Why do we need numbers represented by 2, 8, 16, or 64 digits?"

"It's about how the processor works internally. Very simplistically, if current is flowing through a wire, then we say that it's value is 1; if there is no current, then its value is 0. All numbers are stored in memory cells. These cells have a very basic design. And they can only store 0 or 1."

"But such simplification (only 0 or 1) made it possible to make elements inside the processor and memory very small. Modern processors and memory modules include billions of different elements. And their area is often no more than a square centimeter."

"Whoa. Now I know."

"Now we turn to binary numbers. Here we have the same thing as with octal, only easier."

1) 2 digits are used to write numbers: 0, 1.

2) The number 1012 means 1*22 + 0*21 + 1*20. In other words, it's 1*4+0*2+1*1 =4+1=5110

"Yes. I remember. One cell, which can have a value of either 0 or 1, is called a bit. But it can't store very much information, so they are combined into groups of 8. These groups are called bytes."

"Exactly. A byte is a group of eight bits. It can store the following values: 00000000, 00000001, ... 11111111. These values correspond to the decimal numbers 0,1, ... 255. Which gives us a total of 256 values."

What's the largest integer in Java? Or rather what is its type?

"A long. A long consists of 8 bytes. In other words, 64 bits. It can store values from -263 up to 263-1.

"Yep. I won't touch on how to convert numbers from decimal to binary or vice versa. Otherwise, the lesson would be too long."

"Instead, let's talk a little more about the hexadecimal system."

"Yes, it's very interesting. For the binary and octal systems, we simply got rid of digits, starting with two and eight, respectively. But what do we do here? Add new digits?"

"Exactly! Look at this:"

1) 16 digits are used to write numbers: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F.

2) The number 54316 means 5*162 + 4*161 + 3*160. In other words, it's 5*256+4*16+3*1 = 1280+64+3 = 134710

"So, we just added letters as digits? O_o"

"Yep. And what's the big deal? Why invent new numbers when letters work perfectly well? Check it out:"

Hexadecimal digit Decimal value
0 0
1 1
8 8
9 9
A 10
B 11
C 12
D 13
E 14
F 15

"I'm also not going to talk about converting from decimal to hexadecimal. But here's one interesting fact. A hexadecimal digit is represented by exactly 4 bits, with values from 0 to 15. So, one byte can be written with eight binary digits (0 or 1) or two hexadecimal digits."

"Here's an example:"

Decimal number Binary number Hexadecimal number
0 0000 0000 00
1 0000 0001 01
15 0000 1111 0f
16 0001 0000 10
31 0001 1111 1f
32 0010 0000 20
128 1000 0000 80
129 1000 0001 81
255 1111 1111 ff

"The hexadecimal representation is easily converted to binary (and vice versa). That's why the internal byte representation of a number is rarely given in binary (using 0s and 1s) in programming. That would be too long and difficult to understand. Hexadecimal notation is much more readable and compact."

"I agree. Even I liked it."

"By the way, Java lets you write numbers in various numbering systems directly in the code:"

Base Distinguishing feature Examples Invalid numbers
2 0b at the beginning of the number 0b00001111 0b1111121
8 0 at the beginning of the number 01234343 0128
10 None 95459 909a
16 0x at the beginning of the number 0x10ff 0x1cgh

"Excellent lesson. Thank you, Bilaabo."