Ratios in Common Lisp
Note that fractions (which itself is not a numeric type in Common Lisp) are converted to rationals in Lisp. rational
, ratio
and integer
(and others) are actual numeric types in Common Lisp. If you enter a fraction, it is normalized to a rational (an integer or a ratio number).
CL-USER 16 > 3/9
1/3
CL-USER 17 > 9/9
1
CL-USER 18 > 6/9
2/3
Numeric comparison
When float and ratio are compared, the float value is converted to a rational and then exact comparison is done. See: CLHS, Rule of Float and Rational Contagion.
The ratio is not converted to a float, but the float is converted to a rational.
The problem appears because some floats are not converted to the ratios you would expect. The underlying issue is that floating point numbers have not necessarily an exact representation. The conversion of a non-exact number to an exact rational is not necessary giving the naively expected result.
Unfortunately the conversion of 0.2
to a rational number is not necessarily 1/5
, but this:
CL-USER 7 > (rational 0.2)
13421773/67108864
But 0.5
is 1/2
.
CL-USER 8 > (rational 0.5)
1/2
This is what happens in your examples:
CL-USER 9 > (= 1/2 (rational 0.5))
T
CL-USER 10 > (= 1/5 (rational 0.2))
NIL
So it is not
CL-USER 14 > (= 0.2 (float 1/5))
T
But:
CL-USER 15 > (= (rational 0.2) 1/5)
NIL
Note that the type rational
combines the disjoint subtypes ratio
and integer
. Thus (rational 1.0)
could be an integer, and not a ratio.
(= 0.5 1/2)
returnsT
. 0.5 is terminating in both base 2 and 10: https://mcmap.net/q/15914/-why-can-39-t-decimal-numbers-be-represented-exactly-in-binary – Weig