An Intro to Numeral Systems

A very, very short one, with a focus on binary

Photo by Jon Tyson on Unsplash

Mankind evolved, slowly I might say, from number system to number system and, for now, most of us adopted and use the decimal system in our everyday life.

There are many other numeral systems that we still use for specific tasks and some that are long forgotten.

We'll go through some of them.

An additive numeral system

We’ll start with the Roman numeral system that originated in ancient Rome and remained the usual way of writing numbers throughout Europe well into the Late Middle Ages.

It is an additive system and has 7 symbols (I, V, X, L, C, D, and M corresponding in value to 1, 5, 10, 50, 100, 500, and 1000). The letter N was sometimes used to represent 0 as a standalone number.

The rules are the following:

  • symbols are placed ascending in value from right to left, much like it happens with decimals.
  • any symbol that has a smaller value than the previous one is subtracted from the value of the previous one

If you visit Europe you might see some letters engraved within museums, on buildings, and statues around you. Some of those letters you might also find on your wristwatch.

For example, shown below is the year 1864 (MDCCCLXIV).

Roman numerals on a clock and showing year 1864
Roman numerals on a clock and showing year 1864
Photo by Brady Leavell on Unsplash

Following the previously mentioned rules, MDCCCLXIV = V — I + X + L + C + C + C + D + M and its symbol-by-symbol equivalent in decimal is 1864 = 5–1 + 10 + 50 + 100 + 100 + 100 + 500 + 1000.

A decomposition of the MDCCCLXIV Roman number

As seen above, it is less verbose and easier to read or write 1864 compared to MDCCCLXIV. It is also easier for us, humans, to do some basic math with decimals (add, subtract, multiply, divide).

A curious fact is that the current infamous year, 2020, has the same length in decimal numerals as it has in Roman numerals notation: MMXX.

So there’s no wonder Europeans adopted the decimal system abandoning the Roman one.

A positional numeral system

Numeric keys
Numeric keys
Photo by James Orr on Unsplash

A positional base n numeral system (with n a natural number greater than 1 known as the radix) has n basic symbols (digits) that correspond to the first n natural numbers including 0. The other numerals are obtained using the position of the symbol in the number. Moving from right to left, each symbol value is multiplied by n raised to the power of its position.

Unlike the Roman system which is additive, the decimal system is positional.

Also called base-10 because it uses 10 digits (0 to 9), it is the numeral system we use in our everyday life.

Following the definition from above and using the year 1864 as an example we get:

A decomposition of the 1864 base-10 number

The binary system

Strings of 0s and 1s
Strings of 0s and 1s
Photo by Alexander Sinn on Unsplash

Mankind evolved, slowly I might say, from number system to number system and, for now, most of us adopted and use the decimal system.

On the other side, computers use in their everyday routines the binary numeral system. This is also called the base-2 and uses 0 and 1 as digits.

Following the above definition, and using the year 1864 as an example, which is 11101001000 in binary, we get:

A decomposition of the 11101001000 base-2 number

Comparing 1864 with 11101001000, you can agree that the first one is more human-readable and usable.

Binary operators

From here going forward we’ll use the Dart programming language to exemplify operators, but the science is valid in any programming language.

The operators used within the binary realm are quite different from the ones we use in the decimal system: &, |, ^, ~, >>, and <<.

AND (&) is used to determine whether a particular bit is 1 or 0. This operator takes two equal-length binary representations and performs the logical AND operation on each pair of the corresponding bits. If both bits in the compared position are 1, the bit in the resulting binary representation is 1 otherwise, the result is 0.

assert(1 & 1 == 1);
assert(1 & 0 == 0);
assert(0 & 1 == 0);
assert(0 & 0 == 0);

OR (|) takes two qual-length binary representations and performs the logical inclusive OR operation on each pair of corresponding bits. The result in each position is 0 if both bits are 0, while otherwise the result is 1.

assert(1 | 1 == 1);
assert(1 | 0 == 1);
assert(0 | 1 == 1);
assert(0 | 0 == 0);

XOR (^) is used to switch particular bits between 1 and 0. This operator takes two equal-length binary representations and performs the logical inclusive OR operation on each pair of corresponding bits. The result in each position is 0 if both bits are 0, otherwise the result is 1.

assert(1 ^ 0 == 1);
assert(0 ^ 1 == 1);
assert(1 ^ 1 == 0);
assert(0 ^ 0 == 0);

NOT or complement (~) performs logical negation on each bit. Bits that are 0 become 1, and those that are 1 become 0.

assert(~1 == 0);
assert(~0 == 1);
assert(~0001 == 1110);

Shift left (<<) shifts the bits to the left and zeros are shifted in as new digit.

assert(1 << 1 == 2);

Shift right (>>) shifts the digits to the right and zeros are shifted in to replace the discarded bits.

assert(1 >> 1 == 0);

If you want, you can read more here on Dart operators.

That was a very short and fast introduction to binary, but I hope is good enough for understanding the basics and this bit masking example.

Tha(nk|t’)s all!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store