Links:
11/2/22
The first question we run into is that of defining numbers, as the capabilities and logic of the calculator will depend on the answer. The base-10 system we take for granted is nice, but unwieldy and inefficient to implement with rudimentary electronics.
The base-10 number system has ten fundamental units to convey unique meaning: 0,1,2,3,4,5,6,7,8,9. With electricity, there are only two ways to convey information: off or on, no electricity flowing or yes electricity flowing, 0 or 1. So if we want to use electricity to convey numbers in a base-10 system, we might have to set up something like a grid:
We can define that a column with no information in it represents a 0 in that place. So to represent numbers from 0-999 we'd need control over 27 (3x9) discrete "units of information". Some examples of numbers represented this way:
It definitely seems like we're wasting a lot of space and electronic components (money) conveying no information. For any number 0-999, there's at least 24 out of 27 cells doing nothing.
If electricity has only two ways to convey information, we can try representing numbers using a base-2 system instead of base-10. The columns in the base-10 system above are powers of 10: 10^0=1, 10^1=10, 10^2=100. The base-2 (binary) system will have columns for each power of 2: 2^0=1, 2^1=2, 2^2=4, and so on:
Just looking at the columns, this approach seems less efficient- powers of 2 scale much slower than powers of 10. But now we only have only one row to worry about. We can represent number 0-999 (0-1023 even) with only 10 units of information. Examples:
0011011010
1011000000
1001101101
Converting between from binary back to a decimal number is super easy- same exact process as the base-10 representation:
...though, slightly more tedious to write out this way. We can pack way more information into the same number of "units of information", which we'll call "bits" going forward, using base-2 rather than base-10:
So, surprise: we'll use a binary number system in the calculator. It makes efficient use of the tools we have to use, and this choice will also make arithmetic operations straight-forward, which we'll get to in a future post.
Next question: how many bits do we want to use to represent numbers? I'll leave this question unanswered for now because I'm sure our approach to logic and hardware limitations will eventually dictate the answer. I will give a loose equation for figuring out the eventual answer though.
A calculator should be able to represent very large numbers and very small numbers. The big numbers are simple: the maximum number we can represent scales with the powers of 2, it seems specifically:
So with 10 bits, the largest possible number is 1,023. With 20 bits: 1,048,575. 64 bits: 18,446,744,073,709,600,000. And so on...
The smallest possible positive (non-zero) number we can currently represent is 1. In order to show numbers smaller than 1, one approach is to scale all numbers by a fixed scaling factor. For example, let's scale all numbers by a factor of 1/2^10 or 1/1024. Before if we had the 20 bit binary number:
00000000000000000001
representing the decimal number "1", we now define it as representing 1/1024 (~0.0009766). The number "1024", which would have been represented as:
00000000010000000000
now represents the decimal number "1". We can even throw in a fixed decimal point where it would belong:
0000000001.0000000000
To summarize, here's an example of what each bit could represent:
We'll expand and nail down the final number system in the future (negative numbers?) when we start doing arithmetic. Good for now.
Next up:
Part 2: Basic Arithmetic in Theory
Appendix
After spending a couple weeks testing on pen and paper, figuring out whether I want to use fixed-point or floating-point number representation, and whether I wanted to use a power of 10 or power of 2 scaling factor, I found a really good series of videos that explains most the rationalizing I was doing and the conclusion I came up with (would have saved a lot of time if I had seen this first, but the whole point of this project is to figure things out myself and have fun doing it!). I'll probably dive deeper into the nuance and why I chose to use fixed-point representation with a power of two scaling factor when I write the post on multiplication/division, but since I glossed over the issue here without much explanation, I'll link the videos in case you're curious. Big thank you to Eli Hughes:
Introduction to Fixed Point Math for Embedded Systems (1/3) - https://www.youtube.com/watch?v=bbFBgXndmP0
Introduction to Fixed Point Math for Embedded Systems (2/3) - https://www.youtube.com/watch?v=7pkXlcapNB4
Introduction to Fixed Point Math for Embedded Systems (3/3) - https://www.youtube.com/watch?v=SrELHqRqKjo