9

Most pre-IEEE floating point formats that used biased exponent and a 2's-complement mantissa without a hidden bit, were asymmetric. That is, there was a representable negative value which had no positive equivalent, analogous to 0x80000000 in 32-bit integers.

Printing floating-point numbers typically involved checking if it is negative, negating it if it was, then proceeding with the conversion of the guaranteed non-negative number, taking care to prepend the minus sign if necessary when outputting the text representation.

Naturally, that technique would fail if the argument of the printing routine was the maximal-magnitude negative value. How did the pre-IEEE systems which employed such floating point formats handle the situation? Did any bother to include the code for that special case, or letting the program incur a floating point exception was the norm?

The question is focused on systems with hardware FPUs.

See, for example, a description of the PDP-10 floating point format, mentioning the two's complement format. It says,

Single precision floating point numbers are represented in one 36 bit word as follows:

 0 00000000 011111111112222222222333333
 0 12345678 901234567890123456789012345
 ______________________________________
| |       |                            |
|S| EXP   |     Fraction               |
|_|_______|____________________________|

If S is zero, the sign is positive. If S is one the sign is negative and the word is in twos complement format.

The fraction is interpreted as having a binary point between bits 8 and 9. The exponent is an exponent of 2 represented in excess 200 (octal) notation.

In a normalized floating point number bit 9 is different from bit 0, except in a negative number bits 0 and 9 may both be one if bits 10:35 are all zero. A floating point zero is represented by a word with 36 bits of zero.

Floating point numbers can represent numbers with magnitude within the range 0.5*2^-128 to (1-2^-27)*2^127, and zero. A number that in which bit 0 is one and bits 9-35 are zero can produce an incorrect result in any floating point operation.

from which it is not immediately clear if that restriction makes the useful set of numbers symmetric. Even if it did, how did the printing routines react to the aforementioned bit pattern?

Upd. For the PDP-10 predecessor PDP-6, the floating point format was described in a somewhat more permissive way, see page 27 of the PDF.

For an example of the issue on the CDC 6600 platform, see CERN Computer Newsletter, N 15, page 2, 6600 SYSTEM BUGS:

The input/output conversion routines go into a loop ... the phenomenon appears to be that a number with unnormalised mantissa, and exponent of −0 fails whereas if the mantissa is normalised with exponent −0, conversion is correct.

21
  • 1
    There weren't many FPUs prior to IEEE (aka 8087) and not all base two - like the /360 used base 16.
    – Raffzahn
    Jul 14 at 17:24
  • 2
    @Raffzahn The base is irrelevant for this. What matter is that the IBM format was sign-magnitude rather than 2's complement, so it was not susceptible to that issue.
    – Leo B.
    Jul 14 at 18:28
  • 1
    Of possible interest is Guy Steele and Jon White's “How to Print Floating-Point Numbers Accurately
    – texdr.aft
    Jul 14 at 18:31
  • 1
    @texdr.aft Thank you; I remember hearing about the article, but I have not seen it before; however, the words "negative" and "magnitude" appear only two times each and in irrelevant contexts, which means that the authors were not concerned anymore about asymmetric formats. That is not surprising given the article date (1990, post 1987).
    – Leo B.
    Jul 14 at 18:39
  • 1
    @texdr.aft Thank you, but that is tangential to my question. I want to know if there were platforms which (a) had an asymmetric - for example, 2's complement of some form - f. p. representation, and (b) could handle the "extreme" values in a robust manner. The sole occurrence of "negat" in the article appears in the context implying a symmetric representation.
    – Leo B.
    Jul 20 at 3:57

1 Answer 1

3

The primary advantage of two's-complement numeric representations over other forms is that the bottom bits from an addition or subtraction can be computed in a manner which is agnostic to the signs of the operands. Such an advantage does not apply with floating-point numbers, which require treating operations whose result will be larger than the larger operand differently from those whose result will be smaller. As a consequence, two's-complement floating-point representations have always been rare.

As for more general questions about robustness, many floating-point output routines were designed to output values with somewhat less precision than was available in the underlying types, and produce a value that was hopefully within +/-1 of the least significant digit that was output, but with "hope for the best" rounding semantics beyond that. If one has a floating-point number in the range 0 to 1, a simple way of outputting it would be to do something like:

void out_number(double x)
{
  char dig;
  putchar('.');
  for (int i=0; i<num_digits; i++)
  {
    x*=10.0;
    dig = x;
    x -= dig;
    putchar('0'+dig);
  }
}

Such an approach can easily output any desired number of digits, but will be limited in the number of correct digits it can output, especially when used with values near zero. If the number of digits the function tries to output is limited to what it can handle accurately, there may be no need to do anything fancier, and as a consequence many floating-point implementations didn't.

5
  • 1
    That answer does not answer the question as asked. Sure, there are precise algorithms to output fractional parts of floating-point values, and I'm aware of at least one implementation that used such an algorithm, so that a number represented as 0.1111...111 * 2^0 (with 40 1's in the mantissa) would be printed using the Fortran format F50.45 as 0.999999999999090505298227071762084960937500000 which is (2^40-1)/2^40 exactly.
    – Leo B.
    Jul 14 at 20:09
  • 1
    The document hal.archives-ouvertes.fr/hal-00157268/document (2003) states Few designs, mostly those of Texas Instruments, continue to use two’s complement floating point units. Such units are simpler to build and to validate... The TI format has a hidden bit, but the same must have been true for formats without the hidden bit.
    – Leo B.
    Jul 14 at 20:17
  • @LeoB.: I'll have to take a look at that, but I find dubious the proposition that two's-complement designs are simpler to validate. Maybe the asymmetry is less bad than the way IEEE-754 handles "negative zero", but sign-magnitude math doesn't necessitate such asymmetry. IMHO, zeroes should be made symmetric by having four kinds of zero-ish things: true zero (universal additive identity), positive infinitesimal, negative infinitesimal, and indeterminate-sign infinitesimal [produced by adding any two different infinitesimals].
    – supercat
    Jul 14 at 20:37
  • I've added a concrete example: the PDP-10 had a two's-complement FP format, with some bit patterns declared illegal (or implementation-dependent?).
    – Leo B.
    Jul 14 at 23:01
  • Just adding to @LeoB. 's comment: In 1992 was using a TI C31 DSP as a graphics "Transform and Lighting" accelerator on a prototype 3D PC add-in-board. Had to have functions to map from the PCs IEEE to TI's 2s-complement format. (The need for the DSP disappeared when the Pentium arrived, and the prototype board evolved into PowerVR)
    – Simon F
    Jul 27 at 7:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.