<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    I wondered the same thing. This is exactly how #'%short-float-ratio
    works and I assume it was done for speed reasons. The other big
    mistake in #'%short-float-ratio is probably that it immediately
    checks whether the numerator or denominator is a bignum. That check
    might have been sensible in 32-bit implementations since in those
    implementations the number of significant bits in a fixnum is
    roughly the same as those in a short-float. But such a check doesn't
    make sense in 64-bit implementations:<br>
    <br>
    <font face="monospace">Clozure Common Lisp Version 1.12
      (v1.12-2-g5d13fc7d) DarwinX8664<br>
      ? (integer-length most-positive-fixnum)<br>
      60<br>
      ? (float-digits 1.0s0)<br>
      24</font><br>
    <br>
    Thus by first converting the numerator and denominator to
    short-floats, #'%short-float-ratio is losing a great deal of
    precision immediately, even when both numerator and denominator are
    fixnums.<br>
    <br>
    Assuming we fixed that, we are left with the monotonicity issue that
    Ron points out:<br>
    <br>
    <font face="monospace">; Here's Ron's original example that uses
      rational numbers (more precisely, <i>ratios</i>):<br>
      (let ((a 4110710000054) (b 100000000000))<br>
           (list (float (/ a b)) (float (/ (+ a 1) b)) (float (/ (+ a 2)
      b))))<br>
      ; (41.1071 41.107098 41.1071) ; weird nonmonotonicity<br>
      <br>
      <br>
      ; Reframed to not use any ratios:<br>
      (let ((a 4110710000054) (b 100000000000))<br>
           (list (float (/ (float a 1.0s0)<br>
                           (float b 1.0s0)))<br>
                 (float (/ (float (+ a 1) 1.0s0)<br>
                           (float b 1.0s0)))<br>
                 (float (/ (float (+ a 2) 1.0s0)<br>
                           (float b 1.0s0)))))<br>
      ; (41.1071 41.1071 41.1071) ; [non-strict] monotonicity returns</font><br>
    <br>
    This might be what Ron meant when he said "I'm an idiot" but it also
    took me a while to figure it out: As Ron demonstrated, ratios are
    [effectively] always stored in lowest terms. Because of this, they
    bounce around a lot when you increment the numerator. Which in turn
    causes unpredictable losses of precision: The variance of said
    losses will be large if you always convert numerator and denominator
    to short floats before you divide them. But if you force that lowest
    terms mechanism not to happen, monotonicity returns (second example
    above). So doing ratio conversions with double-floats will be a big
    help. It won't make the nonmonotonicity go away entirely -- there's
    no way to do that because the lowest terms mechanism will still be
    present -- but it will decrease the nonmonotonicity dramatically.<br>
    <br>
    The obvious next step is to remove the bignum check in
    #'%short-float-ratio. I'll try to test that when I have time. The
    test is not trivial because it requires a full rebuild of CCL.<br>
    <br>
    -SS<br>
    <br>
    <br>
    <div class="moz-cite-prefix">On 9/20/21 11:28 AM, Ron Garret wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:E745A05B-9B52-472C-8221-2801B1887A85@flownet.com">
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
      Is there actually a reason, when converting rationals to
      single-floats, that the computation is done by converting the
      numerator and denominator to single-floats and dividing, rather
      than converting them to double-floats, dividing, and then
      converting the result to a single-float?  The former doesn’t seem
      to be appreciably faster on modern hardware:
      <div><br>
      </div>
      <div>
        <div>? (time (dotimes (i 1000000)</div>
        <div>        (let ((x (/ (random 1000000000000) (random
          1000000000000))))</div>
        <div>          (coerce x 'single-float))))</div>
        <div>(DOTIMES (I 1000000) (LET ((X (/ (RANDOM 1000000000000)
          (RANDOM 1000000000000)))) (COERCE X 'SINGLE-FLOAT)))</div>
        <div>took 525,951 microseconds (0.525951 seconds) to run.</div>
        <div>       3,967 microseconds (0.003967 seconds, 0.75%) of
          which was spent in GC.</div>
        <div>During that period, and with 4 available CPU cores,</div>
        <div>     534,009 microseconds (0.534009 seconds) were spent in
          user mode</div>
        <div>       6,094 microseconds (0.006094 seconds) were spent in
          system mode</div>
        <div> 32,000,000 bytes of memory allocated.</div>
        <div> 42 minor page faults, 0 major page faults, 0 swaps.</div>
        <div>NIL</div>
        <div>? (time (dotimes (i 1000000)</div>
        <div>        (let ((x (/ (random 1000000000000) (random
          1000000000000))))</div>
        <div>          (coerce (the double-float</div>
        <div>                       (/ (the doble-float (coerce
          (numerator x) 'double-float))</div>
        <div>                          (the double-float (coerce
          (denominator x) 'double-float))))</div>
        <div>                  'single-float))))</div>
        <div>;Compiler warnings :</div>
        <div>;   In an anonymous lambda form at position 158: Unknown
          type DOBLE-FLOAT, declaration ignored</div>
        <div>(DOTIMES (I 1000000) (LET ((X (/ (RANDOM 1000000000000)
          (RANDOM 1000000000000)))) (COERCE (THE DOUBLE-FLOAT (/ (THE
          DOBLE-FLOAT (COERCE (NUMERATOR X) 'DOUBLE-FLOAT)) (THE
          DOUBLE-FLOAT (COERCE (DENOMINATOR X) 'DOUBLE-FLOAT))))
          'SINGLE-FLOAT)))</div>
        <div>took 542,226 microseconds (0.542226 seconds) to run.</div>
        <div>       8,720 microseconds (0.008720 seconds, 1.61%) of
          which was spent in GC.</div>
        <div>During that period, and with 4 available CPU cores,</div>
        <div>     548,880 microseconds (0.548880 seconds) were spent in
          user mode</div>
        <div>      14,421 microseconds (0.014421 seconds) were spent in
          system mode</div>
        <div> 64,000,000 bytes of memory allocated.</div>
        <div> 2,926 minor page faults, 0 major page faults, 0 swaps.</div>
      </div>
      <div><br>
      </div>
      <div><br>
        <div>
          <div>On Sep 20, 2021, at 10:16 AM, Ron Garret <<a
              href="mailto:ron@flownet.com" moz-do-not-send="true"
              class="moz-txt-link-freetext">ron@flownet.com</a>>
            wrote:</div>
          <br class="Apple-interchange-newline">
          <blockquote type="cite">
            <meta http-equiv="Content-Type" content="text/html;
              charset=UTF-8">
            <div style="word-wrap: break-word; -webkit-nbsp-mode: space;
              -webkit-line-break: after-white-space;">Oh never mind, I’m
              an idiot.
              <div><br>
              </div>
              <div>
                <div>? 4110710000054/100000000000</div>
                <div>2055355000027/50000000000</div>
                <div>? 4110710000055/100000000000</div>
                <div>822142000011/20000000000</div>
                <div>? 4110710000056/100000000000</div>
                <div>513838750007/12500000000</div>
                <div><br>
                </div>
                <div>
                  <div>On Sep 20, 2021, at 9:53 AM, Ron Garret <<a
                      href="mailto:ron@flownet.com"
                      moz-do-not-send="true"
                      class="moz-txt-link-freetext">ron@flownet.com</a>>
                    wrote:</div>
                  <br class="Apple-interchange-newline">
                  <blockquote type="cite">
                    <meta http-equiv="Content-Type" content="text/html;
                      charset=UTF-8">
                    <div style="word-wrap: break-word;
                      -webkit-nbsp-mode: space; -webkit-line-break:
                      after-white-space;">All this is true, but it does
                      not account for the anomaly.  This appears to be a
                      legitimate bug:
                      <div><br>
                      </div>
                      <div>
                        <div>? (let ((a 4110710000054) (b 100000000000))</div>
                        <div>     (list (float (/ a b)) (float (/ (+ a
                          1) b)) (float (/ (+ a 2) b))))</div>
                        <div>(41.1071 41.107098 41.1071)</div>
                      </div>
                      <div>
                        <div>? (mapcar 'decode-float *)</div>
                        <div>(0.64229846 0.6422984 0.64229846)</div>
                        <div><br>
                        </div>
                        <div>It is very data dependent, only manifesting
                          itself for very particular values of A.  I
                          have not yet been able to discern any pattern,
                          but here are a few interesting edge cases:</div>
                        <div><br>
                        </div>
                        <div>
                          <div>? (let ((a 7110710000054) (b
                            100000000000))</div>
                          <div>     (list (float (/ a b)) (float (/ (+ a
                            1) b)) (float (/ (+ a 2) b))))</div>
                          <div>(71.1071 71.10709 71.1071)</div>
                        </div>
                        <div><br>
                        </div>
                        <div>
                          <div>? (let ((a 7110720000054) (b
                            100000000000))</div>
                          <div>     (list (float (/ a b)) (float (/ (+ a
                            1) b)) (float (/ (+ a 2) b))))</div>
                          <div>(71.1072 71.1072 71.1072)</div>
                        </div>
                        <div><br>
                        </div>
                        <div>
                          <div>? (let ((a 4110709000054) (b
                            100000000000))</div>
                          <div>     (list (float (/ a b)) (float (/ (+ a
                            1) b)) (float (/ (+ a 2) b))))</div>
                          <div>(41.10709 41.10709 41.10709)</div>
                        </div>
                        <div><br>
                        </div>
                        <div>AFAICT the bug is in
                          <a class="moz-txt-link-freetext" href="ccl::%short-float-ratio">ccl::%short-float-ratio</a>.  I’ll track it down
                          when I have time, but with the above test
                          cases it should not be too hard to figure it
                          out.</div>
                        <div><br>
                        </div>
                        <div>rg</div>
                        <div><br>
                        </div>
                        <div>
                          <div>On Sep 19, 2021, at 10:56 PM, Raymond
                            Wiker <<a href="mailto:rwiker@gmail.com"
                              moz-do-not-send="true"
                              class="moz-txt-link-freetext">rwiker@gmail.com</a>>
                            wrote:</div>
                          <br class="Apple-interchange-newline">
                          <blockquote type="cite">
                            <meta http-equiv="Content-Type"
                              content="text/html; charset=UTF-8">
                            <div style="word-wrap: break-word;
                              -webkit-nbsp-mode: space; line-break:
                              after-white-space;" class="">
                              <meta http-equiv="Content-Type"
                                content="text/html; charset=UTF-8"
                                class="">
                              <div style="word-wrap: break-word;
                                -webkit-nbsp-mode: space; line-break:
                                after-white-space;" class="">For
                                IEEE-754 single-precision
                                floating-point, the mantissa is held in
                                23 bits. log10 of 2^23 is about 6.9237,
                                so you should expect less than 7 decimal
                                digits of accuracy. 411071.0 is 7
                                digits, so anything after that can (and
                                should) be ignored. The difference
                                between 411071.0 and 411071.03 expressed
                                as a float32 is a single bit: the least
                                significant bit of the mantissa.
                                <div class=""><br class="">
                                </div>
                                <div class="">The reason that coerce
                                  gives a slightly worse result is that
                                  you compute the value as float32, then
                                  convert to float64, and when you print
                                  the number, more digits will be
                                  printed.</div>
                                <div class=""><br class="">
                                </div>
                                <div class="">
                                  <div class=""><br class="">
                                    <blockquote type="cite" class="">
                                      <div class="">On 19 Sep 2021, at
                                        15:05, Steven Nunez <<a
                                          href="mailto:steve_nunez@yahoo.com"
                                          class="moz-txt-link-freetext"
                                          moz-do-not-send="true">steve_nunez@yahoo.com</a>>
                                        wrote:</div>
                                      <br
                                        class="Apple-interchange-newline">
                                      <div class="">
                                        <div class="">
                                          <div class="yahoo-style-wrap"
                                            style="font-family:Helvetica
                                            Neue, Helvetica, Arial,
                                            sans-serif;font-size:13px;">
                                            <div dir="ltr"
                                              data-setdir="false"
                                              class="">Hi folks,</div>
                                            <div dir="ltr"
                                              data-setdir="false"
                                              class=""><br class="">
                                            </div>
                                            <div dir="ltr"
                                              data-setdir="false"
                                              class="">I just posted an
                                              issue regarding what looks
                                              like a <a
                                                href="https://github.com/Clozure/ccl/issues/390"
                                                class=""
                                                moz-do-not-send="true">bug
                                                in rational->float
                                                conversion</a>, and I'm
                                              hoping someone here can
                                              try this on 1.12
                                              (preferably on MS
                                              Windows), or perhaps
                                              provide some insight as to
                                              what might be going on
                                              here for a quick fix.<br
                                                class="">
                                            </div>
                                            <div class=""><br class="">
                                            </div>
                                            <div dir="ltr"
                                              data-setdir="false"
                                              class="">
                                              <div class=""><font
                                                  class=""
                                                  face=""courier
                                                  new", courier,
                                                  monaco, monospace,
                                                  sans-serif">CL-USER>
(lisp-implementation-version)<br class="">
                                                  "Version 1.11.8
                                                  (v1.11.8-2-gd411e378)
                                                  WindowsX8664"<br
                                                    class="">
                                                  CL-USER> (float
                                                  41107100000541273/100000000000)<br
                                                    class="">
                                                  411071.03<br class="">
                                                  <br class="">
                                                  <font class=""
                                                    face=""Helvetica
                                                    Neue",
                                                    Helvetica, Arial,
                                                    sans-serif">Hmm. If
                                                    you work out the
                                                    decimal points, the
                                                    float is:
                                                    411071.00000541273,
                                                    that's a long way
                                                    from .03. Maybe <font
                                                      class=""
                                                      face=""courier
                                                      new",
                                                      courier, monaco,
                                                      monospace,
                                                      sans-serif">coerce</font>?
                                                    Nope, that's even
                                                    worse:</font><br
                                                    class="">
                                                  <br class="">
                                                  CL-USER> (coerce
                                                  41107100000541273/100000000000
                                                  'double-float)<br
                                                    class="">
                                                  411071.03125D0</font><br
                                                  class="">
                                                <br class="">
                                              </div>
                                              <div dir="ltr"
                                                data-setdir="false"
                                                class="">Any ideas?
                                                That's not a small
                                                rounding error.<br
                                                  class="">
                                              </div>
                                              <div dir="ltr"
                                                data-setdir="false"
                                                class=""><br class="">
                                              </div>
                                              <div dir="ltr"
                                                data-setdir="false"
                                                class="">Regards,</div>
                                              <div dir="ltr"
                                                data-setdir="false"
                                                class="">    Steve<br
                                                  class="">
                                              </div>
                                            </div>
                                          </div>
                                        </div>
_______________________________________________<br class="">
                                        Openmcl-devel mailing list<br
                                          class="">
                                        <a
                                          href="mailto:Openmcl-devel@clozure.com"
                                          class="moz-txt-link-freetext"
                                          moz-do-not-send="true">Openmcl-devel@clozure.com</a><br
                                          class="">
                                        <a
                                          href="https://lists.clozure.com/mailman/listinfo/openmcl-devel"
                                          class="moz-txt-link-freetext"
                                          moz-do-not-send="true">https://lists.clozure.com/mailman/listinfo/openmcl-devel</a><br
                                          class="">
                                      </div>
                                    </blockquote>
                                  </div>
                                  <br class="">
                                </div>
                              </div>
                            </div>
_______________________________________________<br>
                            Openmcl-devel mailing list<br>
                            <a href="mailto:Openmcl-devel@clozure.com"
                              moz-do-not-send="true"
                              class="moz-txt-link-freetext">Openmcl-devel@clozure.com</a><br>
                            <a
                              href="https://lists.clozure.com/mailman/listinfo/openmcl-devel"
                              moz-do-not-send="true"
                              class="moz-txt-link-freetext">https://lists.clozure.com/mailman/listinfo/openmcl-devel</a><br>
                          </blockquote>
                        </div>
                        <br>
                      </div>
                    </div>
                    _______________________________________________<br>
                    Openmcl-devel mailing list<br>
                    <a href="mailto:Openmcl-devel@clozure.com"
                      moz-do-not-send="true"
                      class="moz-txt-link-freetext">Openmcl-devel@clozure.com</a><br>
                    <a
                      href="https://lists.clozure.com/mailman/listinfo/openmcl-devel"
                      moz-do-not-send="true"
                      class="moz-txt-link-freetext">https://lists.clozure.com/mailman/listinfo/openmcl-devel</a><br>
                  </blockquote>
                </div>
                <br>
              </div>
            </div>
            _______________________________________________<br>
            Openmcl-devel mailing list<br>
            <a href="mailto:Openmcl-devel@clozure.com"
              moz-do-not-send="true" class="moz-txt-link-freetext">Openmcl-devel@clozure.com</a><br>
            <a class="moz-txt-link-freetext" href="https://lists.clozure.com/mailman/listinfo/openmcl-devel">https://lists.clozure.com/mailman/listinfo/openmcl-devel</a><br>
          </blockquote>
        </div>
        <br>
      </div>
      <br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <pre class="moz-quote-pre" wrap="">_______________________________________________
Openmcl-devel mailing list
<a class="moz-txt-link-abbreviated" href="mailto:Openmcl-devel@clozure.com">Openmcl-devel@clozure.com</a>
<a class="moz-txt-link-freetext" href="https://lists.clozure.com/mailman/listinfo/openmcl-devel">https://lists.clozure.com/mailman/listinfo/openmcl-devel</a>
</pre>
    </blockquote>
    <br>
  </body>
</html>