Neither 1/3 nor 1/10 can be represented accurately by a flonum;
internally we use the closest flonum, but whose exact
value is such a gigantic rational number.

But does that make sense? An inexact number is, after all,
inexact. We can regard a flonum d as an approximation
of any real number within a certain range around d.
There are infinite number of rationals in the range.
Why don't we pick the simpler rational among them?

(Since I sometimes see the argument that floating point
numbers are inexact, I tempted to add a note. A floating point
number itself can be either inexact or exact; there's nothing
inherently inexact in the floating point number representation.
It is the operations on them, in general, that are inexact (when rounding,
overflow or underflow occur). If we use "exact floating point number",
then the above gigantic rational representation is the correct
answer. It is just that Gauche uses floating point representation
for inexact numbers, which allows us to choose alternative rational
representation.)

We already do similar sort of thing in printing flonums; we choose
the shortest decimal representation that can uniquely identify given
flonum.

Now we have rationalize, we can use the same algorithm to find out the simplest rational
number within the precision of a flonum. We can't use rationalize
directly, though, for the error range is more complicated.

In general, any real number r that falls between this range
will be represented by a flonum d:

That is, q is the least quantum representable with the current exponent.

Since Gauche adopts round-to-even rule, the value that exactly falls
between two floating point numbers would belong to the even flonum---
the one whose LSB of mantissa is zero.

This alone makes rationalize short for our purpose, since
it always consider a closed range.

There are also two special cases we need to consider. If a flonum
is a power of two, the flonums below is more "dense" than usual,
so we have smaller lower error range:

d - q/4 <= r <= d + q/2

Also, if d falls under denormalized range, q is fixed to
to the smallest denormalized number.

So we implemented a new procedure real->rational, which
can take individual upper and lower error boundary and a flag
to indicate whether the range is open or not.
Then rationalize can be written on top of it.
Our new exact and inexact->exact calls real->rational
if the argument is inexact real. Here's what you get in HEAD:

gosh> (exact (/ 3.0))
1/3
gosh> (exact 0.1)
1/10

If you need the exact rational representation of d itself,
you can call real->rational with zero error tolerance.