Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Explain why they wasted effort and silicon on insanity:

The 80-bit format has an explicit 1, unlike the normal IEEE float and double.

The chip has BCD support.

There was that idea that the OS would emulate an infinite FP stack via an exception handler.

There was that idea that the OS would emulate more exponent bits via an exception handler messing with the exponents.

The exceptions for imprecise results seem so useless.

We got an 80-bit format, but no 16-bit or 128-bit format. Don't we like powers of two?



Many of your questions are discussed in detail in "The 8087 Primer" [1] but I'll give a quick summary. (I'm not defending their design decisions, just providing what I've read.)

> The 80-bit format has an explicit 1, unlike the normal IEEE float and double.

Apparently the explicit 1 made the hardware much simpler, and with 80 bits it doesn't cost you much to have an explicit 1.

(To explain for others: in the normal float format, the first bit of the mantissa is assumed to be a 1, so this bit is not explicitly stored. This gains you a "free" bit of precision. But then you needs special handling for zero and denormalized numbers because the first bit isn't a 1. The 8087 stores numbers internally using the 80 bit format for increased accuracy. The 80 bit format stores the first bit explicitly, whether it is a 0 or 1.)

> The chip has BCD support.

BCD was a big thing in the 1970s; look at all the effort in the 6502 for BCD support, for instance. My hypothesis is that cheap memory killed off the benefit of packing two digits in a byte.

> We got an 80-bit format, but no 16-bit or 128-bit format.

They did a lot of mathematical analysis to decide that 80 bits for the internal number format would result in accurate 64 bit results. Something about losing lots of bits of accuracy during exponentiation, so you want extra bits the size of the exponent.

> Don't we like powers of two?

Looking at old computers has shown me that word sizes that are powers of two are really just a custom, not a necessity. In the olden days, if your missile needed 19 bits of accuracy to hit its target, you'd build a computer with 19 bit words. And if your instruction set fit in 11 bits, you'd use 11 bit instructions. Using bytes and larger powers of two for words became popular after Stretch and the IBM 360, but other sizes work just fine.

[1] https://archive.org/details/8087primer00palm


> They did a lot of mathematical analysis to decide that 80 bits for the internal number format would result in accurate 64 bit results. Something about losing lots of bits of accuracy during exponentiation, so you want extra bits the size of the exponent.

I'm not sure if it was the reason, but 80-bit intermediate values lets you compute pow(x,y) as exp(y*log(x)) to full precision for the full range of 64-bit floats.


This is likely a big part of it, as the OP has indicated elsethread that a table of log constants are used by the 8087 for calculating logarithms and exponentiations.


My hypothesis — perhaps less informed than yours — is that BCD is a huge efficiency win (a couple of orders of magnitude) for conversion to and from decimal, and a slight loss for internal arithmetic, say about 10% inefficiency. And it avoids worries about fraction roundoff.

So if your data comes from humans and ends up with humans, and in between you have less than a couple hundred calculations, your program is more efficient with BCD, because you don't have to do a dog-slow repeated long division by 0xa to convert to decimal at the end. Somewhere around 1970, this ceased to actually be a big enough inefficiency to matter, but tradition and backward-combatibility kept BCD hardware alive for another 10 or 20 years.


I've come around to the idea that using binary floats in most cases is and was a mistake. Anything that deals with human readable numbers should be a decimal float not binary.


Maybe. It would get rid of some issues but might make people complacent about other issues.

Even then it probably wouldn't be BCD. Too inefficient. The digit-packing versions of IEEE decimals use 10 bits each for blocks of 3 digits. 99.7% efficiency rather than 83% efficiency.


Oh hey, I had no idea about this, thanks! I wrote a short essay about this idea in July ("BCM: binary-coded milial") but I didn't know it was already widely implemented, much less standardized by the IEEE! Do they use 1000s-complement for negative numbers? How does the carry-detection logic work?

I also thought about excess-12 BCM, which simplifies negation considerably, but complicates multiplication.


There's a sign bit, just like binary floating point. The details about how to do the math are up to the implementer, but I'm sure any bignum algorithm would work fine.

https://en.wikipedia.org/wiki/Decimal_floating_point

I can't say I'm a huge fan of the standard defining two separate encodings, one that uses a single binary field, and one that uses a series of 10-bit fields. There's no way to distinguish them either.


I do remember an ON (original nerd) mentioning tracking down a problem (blown nand gate) with a floating point unit. Computer worked fine, passed all the tests but the accounting department was complaining their numbers were coming out wrong.

Problem was with calculating decimal floats which only the accounting department programs used because they used BCD for money.


BCD support was more important for languages that are no longer quite as popular. Having native support made the CPUs look that much better on benchmarks for those particular languages resulting in more business.


re: BCD.

In my limited understanding, there are a variety of approaches to storing decimal numbers exactly. Some of the newer ones are apparently less likely to lead to errors in representation but are more computationally intensive than BCD.


Maybe BCD because otherwise converting from binary to decimal is too painful? Lots of these were used in instrumentation with the classic 7-segment displays.


> The chip has BCD support.

Circa 1980 having BCD support was not seen as insane. Most IBM systems had BCD support (due to the use of BCD for money computations where the different round-off issues with binary vs base-10 are not well tolerated [1]), in fact, even the lowly 6502 (Apple II, Atari, Commodore systems) had BCD support.

The computing world had not yet coalesced around base-2 binary math at the most common one to utilize, so at that time in the past what would have been likely seen as "insane" would have to have not had BCD support. This is also at the tail end of the time frame where one could still find systems with 15-bit bytes and a whole host of other "differences" from what the computing world of today looks like.

[1] https://en.wikipedia.org/wiki/Binary-coded_decimal#Advantage...


In fact, the latest IBM mainframe still has register-to-register BCD arithmetic. [1]

As you say, by the time the 8087 came out you were starting to see some increasing standardization in computer designs (even if systems from different vendors were still incompatible). On the other hand, you still had MPPs, vector supercomputers, Lisp machines, and a bunch of different mainframe designs.

[1] ftp://public.dhe.ibm.com/eserver/zseries/zos/racf/pdf/ny_naspa_2017_10_z14_overview.pdf


Yeah but... this is an FPU. It's a floating-point unit.


"floating point" does not equate to "binary". Floating point simply means that the radix point of a fractional value can be placed at any location relative to the significant digits, i.e., it can 'float'. It says nothing about how the "digits" are encoded.

Decimal floating point (BCD) is a thing, and it is actually part of IEEE 754 (https://en.wikipedia.org/wiki/Decimal_floating_point). Few today pay much attention because everything is binary floating point, but decimal floating point has advantages:

"Working directly with decimal (base-10) fractions can avoid the rounding errors that otherwise typically occur when converting between decimal fractions (common in human-entered data, such as measurements or financial information) and binary (base-2) fractions." (quote is from the wikipedia article cited above). [1]

When the 8087 was designed, there was more use of BCD encodings and more languages that suppored BCD encodings for numerical operations, so providing the ability to also accelerate BCD math operations was just as much a boost for the system as providing acceleration for binary math operations. The computing world was quite different, and by far far less homogeneous, thirty years ago.

[1] More detail on this rounding error referenced is here: https://en.wikipedia.org/wiki/Binary-coded_decimal#Advantage.... The tl;dr variant is that decimal coded fractional values have the identical infinite fractional decimal values (i.e. decimal representation of 1/3) as what one learns in math class in school, so most of us already intuitively know the values where errors can be introduced . Binary values have a much larger number of fractions that require infinite length binary values to represent exactly (i.e. 1/5 (.2) is one example), so one's intuition from decimal fractions no longer applies in all cases.

A little trick I used to play back in the early 80's when it seemed there was a computer store on every corner and at least one IBM-PC on display was to setup a quick BASIC program to count down (subtract) from 100 by a penny (0.01) at a time. On an IBM-PC, since it's BASIC used binary floating point (and likely 32-bit FP as well), this took about 6 loops or so before the IBM-PC was printing 99.939999988733 or some such. On the Atari 800 (which at the time would often be sitting only a few feet away) the same program would count down from 100.00 to 0.00 in 0.01 steps exactly for the entire sequence (the Atari's used BCD floating point, which was why the 'trick' worked). Then for whomever was watching, I'd ask: "Which one do you want balancing /your/ checkbook?" At the time one of the often quoted reasons for "buying a home PC" was "checkbook balancing".

The 'trick' still works with modern systems that use binary, one just has to ask for enough precision that the standard libraries default rounding does not hide the issue from view:

fp.c: #include <stdio.h>

    int main(int argc, char ** argv) {
      double i = 100.0;

      printf("%.40f\n", i);
      i = i - 0.01;
      printf("%.40f\n", i);
    }
Compile: gcc -std=c99 -o fp fp.c

Run: ./fp $ ./fp 100.0000000000000000000000000000000000000000 99.9899999999999948840923025272786617279053

edit: change to be more precise in the meaning of "floating point" in first paragraph.


I recall seeing a comment by Will Kahan that 80-bit bit was intended as an intermediate step: the intention was to eventually go to 128-bit.

Also this was still early days: up until this point, fast floating point was the domain of much more expensive machines. No one had any idea what would be useful in consumer level hardware.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: