Comment 4 for bug 308961

Revision history for this message
David Vázquez (davazp) wrote :

All tests in tests/ directory are passed after of the patch. I include the following tests in tests/print.impure.lisp. This file contains several float point printing tests, so I think it is not required to add more ones.

;;; Tests for bug lp#308961
(assert (string= (format nil "~4,1F" 0.001) " 0.0"))
(assert (string= (format nil "~4,1@F" 0.001) "+0.0"))
(assert (string= (format nil "~E" 0.01) "1.e-2"))
(assert (string= (format nil "~G" 0.01)) "1.00e-2")

About a deeper explication. Well, as I said, the first bug is located in flonum-to-digits function, which is a translation of a Scheme code. The algorithm implemented is supposed to work with positive numbers. However, the function was expanded in order to support rounding its input. So, since 0.001 is round to 0.0, the implemented algorithm fails. This require to understand the algorithm, but I test the lower limit of the interval (r - m-) is positive simply, in order not to generate extra zeros.

The second bug is simpler to explain. format-exp-aux scales a number such that it will have K digits before of the decimal point. This relies on scale-exponent. A example shows the trouble:

(format nil "~E" 0.1)
  0: (FORMAT-EXP-AUX #<SB-IMPL::STRING-OUTPUT-STREAM {AFE5DE9}> 0.1 NIL NIL NIL 1 NIL #\ NIL NIL)
    1: (SB-IMPL::SCALE-EXPONENT 0.1)
    1: SB-IMPL::SCALE-EXPONENT returned 0.1 0
  0: FORMAT-EXP-AUX returned "1"

0.1 is 0.1 * 10^0 according to scale-exponent. Then, it is multiplied by 10^K before printing. This works well.

(format nil "~E" 0.01)
  0: (FORMAT-EXP-AUX #<SB-IMPL::STRING-OUTPUT-STREAM {AA744C1}> 0.01 NIL NIL NIL 1 NIL #\ NIL NIL)
    1: (SB-IMPL::SCALE-EXPONENT 0.01)
    1: SB-IMPL::SCALE-EXPONENT returned 1.0 -2
  0: FORMAT-EXP-AUX returned "2"

In this example, scale-exponent returns 1.0 and -2, meaning 0.01 = 1.0 * 10^-2. Again, format-aux-exp multiply it by 10^K. But as 1.0 has a digit before of the decimal point, the result will have K+1 digits.

This is due to format-exp-aux assumed the returned value will be lesser to 1.0. In order to fix this, I decrement K when scale-exponent return 1.0 as primary value.

Greetings,
David.