Use scientific notation only if there are enough trailing zeroes.
authorMark H Weaver <mhw@netris.org>
Tue, 19 Mar 2013 07:25:59 +0000 (03:25 -0400)
committerMark H Weaver <mhw@netris.org>
Tue, 19 Mar 2013 07:38:15 +0000 (03:38 -0400)
* libguile/numbers.c (idbl2str): Print large numbers in scientific
  notation only if the exponent is >= 7 and the least significant
  non-zero digit has value >= radix^4.

* test-suite/tests/numbers.test ("number->string"): Add tests.

libguile/numbers.c
test-suite/tests/numbers.test

index c641e3f..1f845a3 100644 (file)
@@ -5297,6 +5297,7 @@ idbl2str (double dbl, char *a, int radix)
     int e, k;
     mpz_t f, r, s, mplus, mminus, hi, digit;
     int f_is_even, f_is_odd;
+    int expon;
     int show_exp = 0;
 
     mpz_inits (f, r, s, mplus, mminus, hi, digit, NULL);
@@ -5374,21 +5375,25 @@ idbl2str (double dbl, char *a, int radix)
         }
     }
 
-    if (k >= 8 || k <= -3)
+    expon = k - 1;
+    if (k <= 0)
       {
-        /* Use scientific notation */
-        show_exp = k - 1;
-        k = 1;
-      }
-    else if (k <= 0)
-      {
-        int i;
+        if (k <= -3)
+          {
+            /* Use scientific notation */
+            show_exp = 1;
+            k = 1;
+          }
+        else
+          {
+            int i;
 
-        /* Print leading zeroes */
-        a[ch++] = '0';
-        a[ch++] = '.';
-        for (i = 0; i > k; i--)
-          a[ch++] = '0';
+            /* Print leading zeroes */
+            a[ch++] = '0';
+            a[ch++] = '.';
+            for (i = 0; i > k; i--)
+              a[ch++] = '0';
+          }
       }
 
     for (;;)
@@ -5429,9 +5434,33 @@ idbl2str (double dbl, char *a, int radix)
 
     if (k > 0)
       {
-        for (; k > 0; k--)
-          a[ch++] = '0';
-        a[ch++] = '.';
+        if (expon >= 7 && k >= 4 && expon >= k)
+          {
+            /* Here we would have to print more than three zeroes
+               followed by a decimal point and another zero.  It
+               makes more sense to use scientific notation. */
+
+            /* Adjust k to what it would have been if we had chosen
+               scientific notation from the beginning. */
+            k -= expon;
+
+            /* k will now be <= 0, with magnitude equal to the number of
+               digits that we printed which should now be put after the
+               decimal point. */
+
+            /* Insert a decimal point */
+            memmove (a + ch + k + 1, a + ch + k, -k);
+            a[ch + k] = '.';
+            ch++;
+
+            show_exp = 1;
+          }
+        else
+          {
+            for (; k > 0; k--)
+              a[ch++] = '0';
+            a[ch++] = '.';
+          }
       }
 
     if (k == 0)
@@ -5440,7 +5469,7 @@ idbl2str (double dbl, char *a, int radix)
     if (show_exp)
       {
         a[ch++] = 'e';
-        ch += scm_iint2str (show_exp, radix, a + ch);
+        ch += scm_iint2str (expon, radix, a + ch);
       }
 
     mpz_clears (f, r, s, mplus, mminus, hi, digit, NULL);
index 8f01633..be2e317 100644 (file)
     (pass-if (string=? (number->string 35 36) "z"))
     (pass-if (= (num->str->num 35 36) 35))
 
+    (pass-if (string=? (number->string 12342342340000.0) "1.234234234e13"))
+    (pass-if (string=? (number->string 1234234234000.0) "1234234234000.0"))
+    (pass-if (string=? (number->string 1240000.0) "1240000.0"))
+
     (with-test-prefix "powers of radix"
       (for-each
        (lambda (radix)