DEV Community

Cover image for Numbers According to Computers
Robert Hieger
Robert Hieger

Posted on

Numbers According to Computers

This article was first published on medium.com.

Intended Audience: Beginner to Intermediate Developers

Introduction

Many might consider the topic of this article superfluous and not worthy of lengthy examination if one is looking to become a skilled web developer/designer.

I find that in academic circles and, to a great extent, among budding developers, the importance of understanding numbers as they appear to computers, among other mathematical concepts germane to software development, encounters a kind of flippant dismissal—an assessment that they are not truly necessary in order to become a good software engineer.

I would argue that these rudimentary concepts not only warrant review, but are of increasing importance in the arena of full stack web development/design.

So why spend time on such a boring aspect of computer science? What relevance does it have to a web developer/designer or student of programming? It sounds more like what a computer engineer needs to understand.

Well, yes, a computer engineer definitely must understand binary numbers as microprocessors make us of this at the machine language level to represent data and instructions they receive.

The subject of number representation in computers is of great importance to developers as well, and can have significant ramifications in any programming language. Consider for a moment the shorthand employed to represent numbers in both high level programing languages such as Java, JavaScript or Python and lower level languages such as assembler code or machine language.

Of course, computers don't really know the difference between 10, 100, 35 or 70, for that matter. They don't even know what numbers are. At the level of machine language—the only language of which computers are capable—all the microprocessor understands is electrical current or lack thereof when circuit is closed or open.

At the machine language level, which communicates directly with the microprocessor, 0 represents an open circuit, or one through which the flow of current is interrupted. 1, on the other hand, represents a circuit through which the flow of electricity is not impeded.

A Micro-Exploration of the Microprocessor

In the typical microprocessor there are billions of microcircuits employing silicon semiconductor components.

What is a semiconductor?

At its root, a semiconductor is a

"... material [that] has an electrical conductivity value falling between that of a conductor, such as metallic copper, and an insulator, such as glass. Its resistivity falls as its temperature rises; metals behave the opposite way. Its conducting properties may be altered in useful ways by introducing impurities ('doping') into the crystal structure. When two differently doped regions exist in the same crystal, a semiconductor junction is created"_Semiconductor -Wikipedia).

As further clarified by the Encyclopaedia Britannica, the introduction of impurities through the process of doping starts with

“pure crystalline silicon…which is abundant in ordinary beach sand…[and] has a very high resistance to electrical current…[With the introduction of] certain impurities, known as dopants, the silicon can be made to conduct usable currents… [most notably]…as a switch, turning current off and on as desired” (“Microprocessor Circuits”).

I took this detour because the duality of circuits that can close or open leads logically into how numbers are processed by the microprocessor. The utility of a switch circuit in a computer should be self-evident.

The Binary System (Base 2)

First, we have the binary system, the basis for the ASCII Code (American Standard Code for Information Interchange), which codifies the Latin alphabet, the digits 0-9, punctuation marks, some other special characters and unprintable control characters.

For the purposes of this article, we will concern ourselves solely with the representation of numbers. The ASCII code employs 8 bits to represent a single character. These 8 bits are our starting point to understand the representation of numbers.

How do Computers Count?

I am by no means a mathematician, but the math concepts needed in order to understand binary representation of numbers are present in basic math.

For humans, counting seems most natural in the decimal (Base 10) system, perhaps because we have 10 fingers and 10 toes. The number 10 is an easy concept for us to grasp. Base 10, on the other hand, is completely alien to computers. At the primitive level, there are 2 states for a circuit—closed, where the flow of electricity is uninterrupted, or open, where the flow of current is interrupted, as we discovered in “A Micro-Exploration of the Microprocessor.”

The smallest unit of storage a computer can recognize is called a bit (short for binary digit). A binary digit can be one of two numbers—0 or 1. Because the first widely-used personal computers had microprocessors such as the Intel 8088, whose word length was 8 bits, standard representation for a single character or number now uses the convention of 8 bits.

8 bits are known as a byte. One smaller unit, that of 4 bits is known as a nibble, used only on very early processors that had a 4-bit word length.

What if you need to represent larger numbers or floating point numbers? It is possible to represent larger numbers or floating point numbers. This requires more bytes. On early 8-bit processors, this also requires more than one processing cycle. In this case, the processor’s “[add] instruction set[s] the ‘carry’ flag” and the microprocessor sees the next cycle as part of the same number or calculation (“How Did Old Games and Computers Display Large Numbers?”).

Different programming languages handle representation of numbers differently. We can examine the representation of numeric data types in the C language, which arguably provides the seminal reference types upon which many other languages have built static typing.

As Ritchie and Kernighan state in The C Programming Language,

Chart from The C Programming Language

("2.2 Data Types and Sizes").

What Numbers Can be Expressed by a Single Byte?

To put this in basic mathematical terms, a single byte is capable of representing 28-1 or (2 ×2 ×2 ×2 ×2 ×2 ×2 ×2)-1.

28=256. Why, then, is the largest possible number 256-1? We need one digit to express 0. Therefore, the representable range of numbers expressed by a single byte is 0-255.

Representing Signed Numbers

We cut the possible range of numbers in half if we want to represent negative numbers, with “[the] lowest [negative] number that can be stored [being]
-(2(k-1)-1) and [the] largest [positive] number that can be stored being
(2(k-1)-1) (“Representation of Negative Binary Numbers”).

With this formula, we then have -128 through 127 as the range of numbers one can represent in a single byte (8 bits).

We use the first bit to determine whether a number is negative or positive. We render this notation “with the help of an extra bit or flag called sign bit or sign flag in the Binary number representation system for signed numbers…[and it] has a value of…0 for positive numbers and 1 for negative binary numbers” (“Negative Binary Numbers”).

Using the first bit to represent the sign of the integer has a couple of consequences that bear examination. We now have only 7 bits of the byte to represent the integer. There is also an unsettling ambiguity in this encoding of numbers.

Remember, we have one less binary digit with which to work because we need it to represent 0. If we set the MSB (most significant bit), or the leftmost digit to 0, it represents positive 0. If, on the other hand, the MSB is 1, we now have the theoretical construct of negative 0.

Though the computer will not care one way or the other, this is an unsettling idea for humans, as we conceive of 0 as neither negative, nor positive, but occurring at the center of a number line continuum between the stream of positive integers on the right and the stream of negative integers on the left.

For this reason, the most prevalent representation of signed binary numbers uses the 2s Complement Method, as it produces the least ambiguity of value. In short, 2s Complement represents negative numbers by “invert[ing] the bits (0 goes to 1, and 1 to 0) and add[ing] one to the resulting number” (Finley, “Twos Complement”).

What Does this Look Like in Practice?

Let’s say we want to represent the decimal number -34 using 8 bits. We would start with the unsigned binary representation of 34, which is

0010 0010
OR
0(27) + 0(26) + 1(25) + 0(24) +
0(23) + 0(22) + 0(21) + 1(20) =
010 + 010 + 3210 + 010 +
010 + 210 + 010 = 3410

 

To change the sign of this integer to negative, first we invert each binary digit arriving at

 

1101 1101

 

Finally, we add 1 to the rightmost 7 digits (remembering that the leftmost digit is the MSB representing the sign of the integer). The resulting binary number is

1101 1110

 

which now equals -3410.

Two Other Number Bases Relevant to Computers

There are two other number bases that come into play with computers. By far, the more prevalent of the two is hexadecimal notation, which is Base 16. The other less frequently used number base is octal notation, or Base 8.

Hexadecimal Notation

Hexadecimal notation must represent the numbers 0-15 (16 digits) and does so using the Arabic numerals 0-9 and the Latin alphabetical characters of A-F. As we will see, hexadecimal notation has an intimate relationship to web development and design.

Relevance to Web Development/Design

How is hexadecimal notation relevant to web development and design? From a certain perspective, this question could be likened unto the question of how oxygen is relevant to our pulmonary system. Hexadecimal notation is related fundamentally to both back-end web development and front-end development/design.

In addition to being quite useful to data structures employed on the back-end of web applications, hexadecimal notation is linked intimately to CSS (Cascading Style Sheets) where developers use it to specify colors.

How a monitor displays colors on a web page depends first and foremost upon the color depth afforded by standards of color encoding, and additionally upon what color spaces are supported by the hardware and the browser on which one views the page. Most typical in present day applications is 32-bit color, which supports up to 16,777,216 colors plus “…an alpha channel [that] can create…convincing gradients, shadows and transparencies” (“What's the Difference between 16-Bit, 24-Bit, and 32-Bit Color?”).

24-bit color already provides 16,777,216 colors, but lacks the nuance of the alpha channel provided in 32-bit color encoding.

CSS Color Encoding

Color encoding in CSS is accomplished in several different ways, the most prevalent of which are RGB (red-green-blue), RGBA (red-green-blue-alpha), and HSL (hue-saturation-lightness). There are other means of encoding color. The Mozilla Developer Network published a fascinating article that elucidates the CSS data type, and enumerates keywords that define color using different color spaces, such as sRGB (standard RGB) and HSL, as we’ve already seen. Added to the list, to name but a few, are HSLA (hue-saturation-lightness-alpha) and HWB/HWBA (hue-whiteness-blackness/hue-whiteness-blackness-alpha) (“<color> - CSS: Cascading Style Sheets: MDN”).

All these methods of encoding share one thing in common. They may be expressed in decimal or hexadecimal notation.
For example, the rgb()CSS property uses 8 bits per color channel (red, green and blue).

The syntax to encode the color yellow is rgb(255, 255, 0);

The equivalent syntax to express yellow with hexadecimal notation in CSS is color: #ffff00;

Note that the rgb() property has 3 decimal numbers with a range of 0-255. Each of these decimal numbers is represented as 8 bits, for a total of 24 bits, corresponding to the 24-bit color encoding mentioned above.

Since we are dealing with unsigned integers, we can dispense with 2s complement encoding for the moment.

This would give us the following binary representation of the color yellow:

11111111 11111111 00000000

 

The hexadecimal equivalent is three groupings of 2 hexadecimal digits:

FF FF 00

 

Note that two hexadecimal digits are equivalent to 8 bits. Consequently, a total of 6 hexadecimal digits do the same job that 24 binary digits do. Quite a reduction in time spent on encoding color.

Three Different Ways of Counting

To show the means of counting provided by number bases historically used in computing, let’s take a look at their efficiency (from the human perspective, anyway) of notation from least to most:

Counting in Binary

0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010

 

And what does the large binary number of 1010 equal in Base 10? Here is the astonishing equivalency between the two:

10102 = 1(23) + 0(22) + 1(21) + 0(20) = 1010

 

Counting in Octal

Octal notation or Base 8 is perhaps a bit less daunting. Here is how we count in Base 8:

0, 1, 2, 3, 4, 5, 6, 7, 10, 11, 12, 13, 14, 14, 15, 16, 17, 20…77, 100

Here, we have a total of 8 digits representing the values from 0-7. So what is the equivalent of 1008? Here is the equation:

1008 = 1(82) + 0(81) + 0(80) =
6410 + 010 + 010 = 6410

 

As mentioned earlier, octal notation does not come into a lot of use in present computer platforms. Its chief usage was with old minicomputers and mainframes such as the IBM System/360, “announced by IBM on April 7, 1965…[and]…designed to cover both commercial and scientific applications and to cover a complete range of applications from small to large” (“IBM System/360 - Wikipedia”).

Counting in Hexadecimal

At first glance, counting in hexadecimal (Base 16) is daunting because one must represent the numbers 0-15 with single digits. Thus we count like this:

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F,
10, 11, 12, 13, 14, 15, 1A, 1B, 1C, 1D, 1E, 1F, 20…

 

This schema challenges our perception. After all, we do not have 16 fingers with which we can count 16 digits. To our way of thinking, 16 is 1 unit of ten plus 6 ones. But now let’s see the equivalent of 1A in decimal:

1A16 = 1(161) + A(160) =
1610 + 1010 = 2610

 

This representation is nice and compact. But its real advantage becomes more obvious in the representation of larger numbers, such as those uses to represent color in CSS.

As we know, each hexadecimal digit is equivalent to 4 bits (1 nibble). Because a byte is comprised of 8 bits, what is represented in 8 digits in binary can be represented in only 2 digits in hexadecimal. This proves quite advantageous for coding in CSS.

Each channel—red, green and blue—have a decimal value of 192, which when notated using the rgb() property of CSS is rgb(192, 192, 192); Though not as cumbersome as the binary notation specified above, I think we can agree that it is yet more compact to use the hexadecimal CSS rule for the color silver—color: #c0c0c0;

 

Conclusion

We have covered in some depth the seemingly arcane, yet vital concept of number encoding on computers and distilled this knowledge through the looking glass of web design/development. Though not linked pronouncedly to the technologies of web development and design, the importance of number encoding to web technologies is irrefutable and overarching.

In today’s world wide web, what we used to call web sites are undeniably trending toward web applications with far more user interaction than ever before, and beginning to look more like their desktop counterparts.

As a result, web applications can involve manipulation of numbers, often at a more sophisticated level than previously encountered.

Finally, if we are truly honest with ourselves, sometimes when we do need to bother with the complexities of binary or hexadecimal calculations, it can become tedious and frustrating because our skills have become a bit rusty.
The intention of this article is to give some underpinning, and perhaps a new appreciation for these concepts by those who have long been away from rudimentary theory.


References

“Semiconductor.” Wikipedia, Wikimedia Foundation, 30 May 2022,
     https://en.wikipedia.org/wiki/Semiconductor.

“Microprocessor Circuits.” Encyclopædia Britannica, Encyclopædia
     Britannica, Inc.,
     https://www.britannica.com/technology/integrated-circuit/Microprocessor-circuits.

“R/Explain Like I’m Five - ELI5: How Did Old Games and Computers Display
     Large Numbers?” Reddit, Reddit.com,
     https://www.reddit.com/r/explainlikeimfive/comm ents/5vqye0/eli5_how_did_old_games_and_computers_display/

Kernighan, Brian W., and Dennis M. Ritchie. “2.2 Data Types and Sizes.” The
     C Programming Language
, Prentice Hall, Englewood Cliffs, NJ, 2016.

“Representation of Negative Binary Numbers.” GeeksforGeeks, 22 Apr. 2020,https://www.geeksforgeeks.org/representation-of-negative-binary-numbers.

Finley, Thomas. “Two's Complement.” Duke CPS 104 Codex,
     Cornell University,
     Apr. 2000,
     https://www.cs.cornell.edu/~tomf/notes/cps104/twoscomp.html.

“What's the Difference between 16-Bit, 24-Bit, and 32-Bit Color?”
     Computer Hope'sFree Computer Help, Computer Hope, 13 Nov. 2018,
     https://www.computerhope.com/issues/ch001557.htm#:~:text=Like%2024%Dbit%20olor%2C%2032,colors%2C%20more%20memory%20is%20required.

“<color> - CSS: Cascading Style Sheets: MDN.”
     CSS: Cascading Style Sheets | MDN, Mozilla Developer Network,
     https://developer.mozilla.org/en-US/docs/Web/CSS/color_value.

“IBM System/360.” Wikipedia, Wikimedia Foundation, 22 Feb. 2021,
     https://en.wikipedia.org/wiki/IBM_System/360.

Top comments (0)