How to print floating-point numbers accurately

Guy L. Steele, Jon L. White
2004 SIGPLAN notices  
History Our PLDI paper [28] was almost 20 years in the making. How should the result of dividing 1.0 by 10.0 be printed? In 1970, one usually got "0.0999999" or "0.099999994"; why not "0.1"? (The problem of binary-to-decimal conversion is amazingly tricky, even for fixed-point fractions, let alone floatingpoint numbers [31][22][20] [12] .) Some programming systems of the day required a prespecified limit for the number of decimal digits to be printed for a binary floating-point number. If, in
more » ... r example, the limit were set to nine decimal places, then the printed result might well be 0.099999994; but if the limit were set to seven decimal places, then poorly implemented printers would produce 0.0999999 and those that took the trouble to perform decimal rounding would produce either 0.1000000 or 0.1. What is the correct number of digits to produce if the user doesn't specify? If a system prints too many digits, the excess digits may be "garbage," reflecting more information than the number actually contains; if a system prints too few digits, the result will be wrong in a stronger sense: converting the decimal representation back to binary may not recover the original binary value. It really bugged one of us (White) that systems of the day not only produced incorrect decimal representations of binary numbers, but provided no guaranteed bound on how wrong they might be. In early 1971, he began to analyze the machine-language algorithm used in the implementation of MacLisp [23][27] to convert PDP-10 floating-point numbers into decimal notation. He also investigated the behavior of other language systems, both those that printed a variable number of digits and those that printed a fixed number of digits but failed to perform decimal rounding correctly. Using the "bignum" (high-precision integer) facilities that had recently been added to MacLisp for other purposes, White investigated the exact representations of certain floating point numbers that seemed to print out with too many decimal digits. He discovered that virtually all of the systems he examined suffered from one or more of the following problems on many floating-point values: (a) printing many more decimal digits than were necessary, (b) printing decimal values that differed from the binary values by many units in the last place (ulps), and (c) exhibiting substantial "drift" when a value is printed, then read back in, the new value printed and again read back in, and so on. White found that the programmers or authors of these systems invariably claimed that their systems must be producing "correct" results because (1) they produced lots of decimal digits, making no claim of producing "shortest" representations, and/or (2) they 20
doi:10.1145/989393.989431 fatcat:nigbcymncvbchcgajc3fk7qhay