[Openmcl-devel] Error in rational -> float conversion

Ron Garret ron at flownet.com
Mon Sep 20 10:28:45 PDT 2021


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:

? (time (dotimes (i 1000000)
        (let ((x (/ (random 1000000000000) (random 1000000000000))))
          (coerce x 'single-float))))
(DOTIMES (I 1000000) (LET ((X (/ (RANDOM 1000000000000) (RANDOM 1000000000000)))) (COERCE X 'SINGLE-FLOAT)))
took 525,951 microseconds (0.525951 seconds) to run.
       3,967 microseconds (0.003967 seconds, 0.75%) of which was spent in GC.
During that period, and with 4 available CPU cores,
     534,009 microseconds (0.534009 seconds) were spent in user mode
       6,094 microseconds (0.006094 seconds) were spent in system mode
 32,000,000 bytes of memory allocated.
 42 minor page faults, 0 major page faults, 0 swaps.
NIL
? (time (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))))
;Compiler warnings :
;   In an anonymous lambda form at position 158: Unknown type DOBLE-FLOAT, declaration ignored
(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)))
took 542,226 microseconds (0.542226 seconds) to run.
       8,720 microseconds (0.008720 seconds, 1.61%) of which was spent in GC.
During that period, and with 4 available CPU cores,
     548,880 microseconds (0.548880 seconds) were spent in user mode
      14,421 microseconds (0.014421 seconds) were spent in system mode
 64,000,000 bytes of memory allocated.
 2,926 minor page faults, 0 major page faults, 0 swaps.


On Sep 20, 2021, at 10:16 AM, Ron Garret <ron at flownet.com> wrote:

> Oh never mind, I’m an idiot.
> 
> ? 4110710000054/100000000000
> 2055355000027/50000000000
> ? 4110710000055/100000000000
> 822142000011/20000000000
> ? 4110710000056/100000000000
> 513838750007/12500000000
> 
> On Sep 20, 2021, at 9:53 AM, Ron Garret <ron at flownet.com> wrote:
> 
>> All this is true, but it does not account for the anomaly.  This appears to be a legitimate bug:
>> 
>> ? (let ((a 4110710000054) (b 100000000000))
>>      (list (float (/ a b)) (float (/ (+ a 1) b)) (float (/ (+ a 2) b))))
>> (41.1071 41.107098 41.1071)
>> ? (mapcar 'decode-float *)
>> (0.64229846 0.6422984 0.64229846)
>> 
>> 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:
>> 
>> ? (let ((a 7110710000054) (b 100000000000))
>>      (list (float (/ a b)) (float (/ (+ a 1) b)) (float (/ (+ a 2) b))))
>> (71.1071 71.10709 71.1071)
>> 
>> ? (let ((a 7110720000054) (b 100000000000))
>>      (list (float (/ a b)) (float (/ (+ a 1) b)) (float (/ (+ a 2) b))))
>> (71.1072 71.1072 71.1072)
>> 
>> ? (let ((a 4110709000054) (b 100000000000))
>>      (list (float (/ a b)) (float (/ (+ a 1) b)) (float (/ (+ a 2) b))))
>> (41.10709 41.10709 41.10709)
>> 
>> AFAICT the bug is in ccl::%short-float-ratio.  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.
>> 
>> rg
>> 
>> On Sep 19, 2021, at 10:56 PM, Raymond Wiker <rwiker at gmail.com> wrote:
>> 
>>> 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.
>>> 
>>> 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.
>>> 
>>> 
>>>> On 19 Sep 2021, at 15:05, Steven Nunez <steve_nunez at yahoo.com> wrote:
>>>> 
>>>> Hi folks,
>>>> 
>>>> I just posted an issue regarding what looks like a bug in rational->float conversion, 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.
>>>> 
>>>> CL-USER> (lisp-implementation-version)
>>>> "Version 1.11.8 (v1.11.8-2-gd411e378) WindowsX8664"
>>>> CL-USER> (float 41107100000541273/100000000000)
>>>> 411071.03
>>>> 
>>>> Hmm. If you work out the decimal points, the float is: 411071.00000541273, that's a long way from .03. Maybe coerce? Nope, that's even worse:
>>>> 
>>>> CL-USER> (coerce 41107100000541273/100000000000 'double-float)
>>>> 411071.03125D0
>>>> 
>>>> Any ideas? That's not a small rounding error.
>>>> 
>>>> Regards,
>>>>     Steve
>>>> _______________________________________________
>>>> Openmcl-devel mailing list
>>>> Openmcl-devel at clozure.com
>>>> https://lists.clozure.com/mailman/listinfo/openmcl-devel
>>> 
>>> _______________________________________________
>>> Openmcl-devel mailing list
>>> Openmcl-devel at clozure.com
>>> https://lists.clozure.com/mailman/listinfo/openmcl-devel
>> 
>> _______________________________________________
>> Openmcl-devel mailing list
>> Openmcl-devel at clozure.com
>> https://lists.clozure.com/mailman/listinfo/openmcl-devel
> 
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> https://lists.clozure.com/mailman/listinfo/openmcl-devel

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.clozure.com/pipermail/openmcl-devel/attachments/20210920/e7efc71b/attachment.htm>


More information about the Openmcl-devel mailing list