Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

irrational behaviour? #913

Open
mayer-goldberg opened this issue Feb 8, 2025 · 5 comments
Open

irrational behaviour? #913

mayer-goldberg opened this issue Feb 8, 2025 · 5 comments

Comments

@mayer-goldberg
Copy link

Does this behaviour make sense??

Chez Scheme Version 9.5.8
Copyright 1984-2022 Cisco Systems, Inc.

> (rational? 4.56)
#t
> (rational? (sqrt 2))
#t
> (rational? (log 5))
#t
@soegaard
Copy link
Contributor

soegaard commented Feb 8, 2025

This follows the specification.

The notation 4.56 denotes the number 4.56=456/1000 which is rational.
The return value of (sqrt 2) is a floating point number with finite precision - so also a rational.
In a (hypothetical?) implementation that also supported exact square roots,
the predicated rational? would be more useful.
Now, the role of rational? is to weed out infinities.

(rational? obj)‌‌procedure
(integer? obj)‌‌procedure
...
If x is a real number object, then (rational? x) is true if and only if there exist exact integer objects k1 and k2 such that (= x (/ k1 k2)) and (= (numerator x) k1) and (= (denominator x) k2) are all true. Thus infinities and NaNs are not rational number objects.

@mayer-goldberg
Copy link
Author

Chez supports rational roots.

If your explanation about 4.56 were correct, then the following behaviour would have been incorrect, wouldn't it?

> (exact? 4.56)
#f

How can 4.56 be both rational and inexact if it denotes precisely 456/100?

@soegaard
Copy link
Contributor

soegaard commented Feb 8, 2025

My own thinking:

As a concept the number 4.56 itself is always exact.
In a computation the result can be be derived by an inexact process though.
So an inexact 4.56 is a rational number, but an inexact number or operation was used to compute it.

The spec:

= Numbers =

This chapter describes Scheme's model for numbers. It is important to distinguish between the mathematical numbers, the Scheme objects that attempt to model them, the machine representations used to implement the numbers, and notations used to write numbers. In this report, the term number refers to a mathematical number, and the term number object refers to a Scheme object representing a number. This report uses the types complex, real, rational, and integer to refer to both mathematical numbers and number objects. The fixnum and flonum types refer to special subsets of the number objects, as determined by common machine representations, as explained below.

= Exactness =

It is useful to distinguish between number objects that are known to correspond to a number exactly, and those number objects whose computation involved rounding or other errors. For example, index operations into data structures may need to know the index exactly, as may some operations on polynomial coefficients in a symbolic algebra system. On the other hand, the results of measurements are inherently inexact, and irrational numbers may be approximated by rational and therefore inexact approximations. In order to catch uses of numbers known only inexactly where exact numbers are required, Scheme explicitly distinguishes exact from inexact number objects. This distinction is orthogonal to the dimension of type.

A number object is exact if it is the value of an exact numerical literal or was derived from exact number objects using only exact operations. Exact number objects correspond to mathematical numbers in the obvious way.

Conversely, a number object is inexact if it is the value of an inexact numerical literal, or was derived from inexact number objects, or was derived using inexact operations. Thus inexactness is contagious.

Exact arithmetic is reliable in the following sense: If exact number objects are passed to any of the arithmetic procedures described in section 11.7.1, and an exact number object is returned, then the result is mathematically correct. This is generally not true of computations involving inexact number objects because approximate methods such as floating-point arithmetic may be used, but it is the duty of each implementation to make the result as close as practical to the mathematically ideal result.

@melted
Copy link
Contributor

melted commented Feb 10, 2025

Chez supports rational roots.

If your explanation about 4.56 were correct, then the following behaviour would have been incorrect, wouldn't it?

> (exact? 4.56)
#f

How can 4.56 be both rational and inexact if it denotes precisely 456/100?

It's an inexact literal, that means it's not assumed to be an exact number. It is precisely 456/100, but every inexact number is a precise number that approximates some number.

If you actually divide 456 by 100, exact? will return #t.

> (exact? (/ 456 100))
#t

or as a ratio literal

> (exact? 456/100)
#t

@dpk
Copy link

dpk commented Mar 2, 2025

Does this behaviour make sense??

Chez Scheme Version 9.5.8
Copyright 1984-2022 Cisco Systems, Inc.

> (rational? 4.56)
#t
> (rational? (sqrt 2))
#t
> (rational? (log 5))
#t

In contrast to most languages where numeric types are based on their machine representations, Scheme takes a mathematical view of numbers as far as possible – but only as far as possible.

4.56, as @soegaard noted, is mathematically speaking a rational number. It is represented, in this case, as a floating-point value. The name for this in Scheme is an inexact rational. What I think (?) you’re expecting based on your question is for rational? to say #f because it’s not written 456/100. That is an exact rational (and still rational); Scheme will represent it not as a float, but as a pair of arbitrarily-large integers (114 and 25) for the numerator and denominator.

With your next two examples, we unfortunately reach the ‘as far as possible’ part. The Scheme sqrt and log procedures are not the mathematical sqrt and log functions whose results may well be irrational. Instead, these procedures return inexact, rational approximations of the mathematical results. (In other words, you aren’t asking if the square root of 2 is rational; you’re asking if the inexact, rounded-off result of the Scheme sqrt procedure is rational, which it is. You can even ask for its numerator and denominator!)

Many years ago there was a proposal to clean up the semantics and terminology here, but aside from some minor patches in the R6RS spec compared to R5RS, it didn’t really go anywhere. The exactness/inexactness situation has some weird edge cases like this but it seems we’re stuck with it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants