# Why did decimal arithmetic slow down VisiCalc?

There is an excellent article about VisiCalc that goes into all the details about what happened and why, highly recommended if you are interested in that part of computing history. I was reading this section:

At its heart, VisiCalc is about numbers. One of the early decisions we made was to use decimal arithmetic so that the errors would be the same one that an accountant would see using a decimal calculator. In retrospect this was a bad decision because people turn out to not care and it made calculations much slower than they would have been in binary.

And nodding, yes, VisiCalc's successors backslid in this regard; to this day, the Internet is full of questions and answers about why Excel exhibits anomalies with numbers like 0.1 and binary floating point not rounding the way people expect. VisiCalc should really have launched an advertising campaign at the time pointing out the...

... Wait a minute. Fridge logic.

VisiCalc was written on the 6502, which supports BCD arithmetic. You just have to turn on decimal mode, and the CPU will add BCD bytes at exactly the same speed as it would add binary bytes.

But most numbers in a spreadsheet are simple when expressed in decimal. A number like 1234.56 takes three bytes in BCD where it would've taken eight bytes in double precision binary floating point. That not only saves memory but, if your calculation routines (which have to be done in software – the machine had no FPU) take the opportunity for early exit, also saves time. So calculation of numbers that typically occur in spreadsheets should be faster in decimal.

And small spreadsheets spend a lot of their time updating the display. Converting a number from internal representation to ASCII for display is quite a bit faster when the internal representation was decimal.

So why did he say decimal made calculations slower?

A number like 1234.56 takes three bytes in BCD where it would've taken eight bytes in double precision binary floating point.

Generally speaking, that is not the case. If you have a database field definition of 6 digits total, 4 before the decimal, 2 after, positive numbers only, then yes you can have 1234.56 represented in 3 8-bit BCD bytes. But if, as is more typically the case:

• You allow any number to have many more digits - e.g., 8 digits is a minimum just to allow up to (but not including) \$1,000,000 specified to the penny. More typical would be 10 or 12 or more.
• You allow varying numbers of digits past the decimal place in different fields - e.g., 2 for US (and many other) currency values, but 6 or more for unit costs (e.g., cost of kWh for utility bills)
• You allow negative numbers.

Then you very quickly go beyond 3 bytes. 8 bytes becomes a reasonable minimum.

Even for storage (ignoring calculation), 3 bytes doesn't work for the 6-digit number because something somewhere has to define that this cell has a 3-byte positive number with the decimal point before the last 2 digits. That takes a byte, so now we are at 4 bytes.

In addition, the code needed for the extra manipulations (code/decode different length numeric formats) eats into the very limited 64k code + data available on typical 8-bit systems. It could easily be the case that the space saved for values by varying size (and hopefully on average much smaller) of numeric cells in a spreadsheet would typically be outweighed by the extra code needed in memory to support display, manipulation and calculation of those numbers.

6502 supported SIMPLE BCD arithmetic. I would bet that the VisiCalc guys in the end didn't even use that feature and wrote the whole thing from scratch. There's not just addition and subtraction, there's also multiplication and division, plus VisiCalc was floating point (just decimal floating point).

The reason the decimal math is slower is simply the same reason "nobody" uses decimal math today, they use binary math. With binary math, each bit is a digit. With decimal math, 4 bits is a digit. More memory for less precision, the math is just slower, its just a lot more work for the computer, even the 6502 with nascent support for it.

(And, yes, decimal math is used all over the place in different places, but it's the exception not the rule.)

• First paragraph: yes but the same is true of binary. All the 6502 can natively do is add or subtract one byte at a time, regardless of whether you are working decimal or binary; everything beyond that still has to be implemented in software regardless. Nov 22, 2020 at 16:02
• Second paragraph: in a sense that is true, but in practice for serious work one tends to use 8 bytes either way, which represents 14 decimal digits in BCD or ~16 decimal digits equivalent in binary; there is a sense in which the latter is more efficient, but it should be the same speed either way. And as I observed, in a spreadsheet with BCD you can usually early exit so it would actually be much faster. Nov 22, 2020 at 16:06
• Third paragraph: nowadays typical CPUs provide hardware support for binary floating point but not for BCD, which makes the former clearly advantageous, but that was not true of the 6502. (Or the Z80, the second CPU on which VisiCalc ran.) Nov 22, 2020 at 16:07
• Perhaps I should put it more bluntly. How do I know the BCD math is slower than binary math? Because we don't do it. Because it's the exception, rather than the rule. Because the benefits of binary math (precision, memory, speed) outweigh the benefits of decimal math for most applications. Because people far, far smarter than I in the field still do binary math. Even though co-processors such as the 8087 support decimal math, as rule, it's still not done. Despite all of the advances over the years, the gross "we", "everybody", don't do it. That's how I know. Nov 22, 2020 at 18:03
• @WillHartung "With binary math, each bit is a digit. With decimal math, 4 bits is a digit" only for different definitions of digit in each place. We (here) may not do decimal maths in computers, but most financial transactions that govern our lives are done as decimals in SQL databases and COBOL Nov 22, 2020 at 20:03

Because decimal operations are slower, even on the 6502. There is processor support for 8-bit BCD addition and subtraction, but that's it.

Code for decimal multiplication, division, shifting, floating point normalization, and maybe even comparison, will be somewhat larger and slower than with binary.

For example, shift-and-subtract division routines require a subroutine to halve the value. In binary this is trivial. Using an 8 bit value as an example:

``````        LSR
``````

In decimal mode, it'll be something like this (courtesy of "Multiplying and Dividing in Decimal Mode"):

``````        ROR
N08     PHP
BPL HALF2
SEC
SBC #\$30
HALF2   BIT N08
BEQ HALF3
SEC
SBC #3
HALF3   PLP
``````

Code like this would be in the inner loop of a decimal divide routine. The speed penalty is significant.

• But in binary, there is also processor support for 8-bit addition and subtraction, but that's it. So binary versus decimal makes no difference there. Nov 22, 2020 at 17:38
• I have expanded my answer with an example that should make it clear. Nov 22, 2020 at 18:05
• Okay, fair point! Nov 22, 2020 at 18:14
• In addition to add and subtract, the 6502 also had AND (multiply bits), and shift (multiply/divide by 2) operations, useful as building blocks for binary multiply and divide. It did not have corresponding elementary decimal operations, so those needed to be synthesized, making the code slower and more complex. Nov 23, 2020 at 14:02