[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: comparison operators and *typos
| Date: Mon, 27 Jun 2005 18:09:04 -0400
| From: Paul Schlie <schlie@xxxxxxxxxxx>
| > From: Aubrey Jaffer <agj@xxxxxxxxxxxx>
| > | Date: Mon, 27 Jun 2005 02:29:12 -0400
| > | From: Paul Schlie <schlie@xxxxxxxxxxx>
| > | ...
| > | Thereby one could define that an unsigned 0 compares = to signed 0's to
| > | preserve existing code practices which typically compare a value against
| > | a sign-less 0. i.e.:
| > |
| > | (= 0 0.0 -0 -0.0) => #t
| > | (= 0 0.0 +0 +0.0) => #t
| > |
| > | (= -0 -0.0 +0 +0.0) => #f
| > The `=' you propose is not transitive, which is a requirement of R5RS.
| - then alternatively one could define:
| (= -0 -0.0 0 0.0 +0 +0.0) => #t
| while retaining the remaining relationships, as it seems
| that = and < relationships need not be mutually exclusive?
-- procedure: = z1 z2 z3 ...
-- procedure: < x1 x2 x3 ...
-- procedure: > x1 x2 x3 ...
-- procedure: <= x1 x2 x3 ...
-- procedure: >= x1 x2 x3 ...
These procedures return #t if their arguments are (respectively):
equal, monotonically increasing, monotonically decreasing,
monotonically nondecreasing, or monotonically nonincreasing.
These predicates are required to be transitive.
Equal cannot be monotonically increasing.
| > Mathematical division by 0 is undefined; if you return 1, then code
| > receiving that value can't detect that a boundary case occured.
| - yes, as above; and corrected below for unsigned 0's and 0.0's:
| 1/0 == inf :: 1/inf == 0 :: 0/0 == inf/inf == ~1
| where although inf equivalent in magnitude to +/-inf,
| it's sign is is undefined, thereby similar to nan, with
| the exception that if one were to introduce the convention
| that '~' may designate an ambiguous sign then the result of
| any division by inf or 0 may be considered to only yield
| an ambiguous sign although not necessarily magnitude, in
| in lieu of considering the value as undefined, i.e.
| inf => ~inf ; either +inf or -inf
| (* 3 (/ 0 0)) => ~3 ; either -3 or +3, thereby:
| (abs (* 3 (/ 0 0))) => +3
So ~ generates an algebraic field extension attaching the roots of
x^2=1. Note that ~ is not a real number because it doesn't fit in the
| (as this is how an implementation would behave if it considered
| +-inf and +-0 it's greatest and smallest represent-able but
| non-accumulating values; which effectively enables calculations
| to loose precision more gracefully, than falling of the edge of
| the value system potentially resulting in a run-time fault.)
Section 6.2.2 Exactness says:
If two implementations produce exact results for a computation that
did not involve inexact intermediate results, the two ultimate
results will be mathematically equivalent.
So loss of precision must not be platform dependent; thresholds of
"greatest and smallest represent-able" values can not affect
precision. Losing precision in calculation is an attribute of inexact
| > ...
| > Nearly all of the SLIB occurences of EXPT have at least one
| > literal constant argument. In these cases, (expt 0 0) signaling
| > an error would catch coding errors. MODULAR:EXPT tests for a
| > zero base (and returns 0) before calling EXPT.
| - ??? The responsibility of an implementation's arithmetic
| implementation is to be generically as correct and consistent as
| reasonably possible. If slib chooses to optionally signal a
| runtime error for any arbitrary set of argument values, that's it's
| prerogative; but should have nothing to do with what the arithmetic
| value of (expt 0 0) or any other function is most consistently
| defined as being.
My point is that (expt 0 0) is unlikely to occur when EXPT is being
used as a continuous function; its occurrences will be exponentiating
integers. In the integer context, arguments about limits of
continuous functions are irrelevant.
| (all arithmetic functions should always return values).
6.2.3 Implementation restrictions:
If one of these procedures is unable to deliver an exact result when
given exact arguments, then it may either report a violation of an
implementation restriction or it may silently coerce its result to
an inexact number.
Always returning a value is a stronger requirement than R5RS or
SRFI-70, which gives the implementation a choice between returning 0/0
and signaling an error for (/ 0.0 0.0). Can you justify that mandate?
Do you consider QUOTIENT, MODULO, and REMAINDER arithmetic?
| > Grepping through a large body of Scheme code found no use of EXPT
| > where the two arguments are related.
| - which has nothing to do with anything, functions should be considered
| to be evaluated about static points:
| i.e. (f x y) == (f (+ x ~1/inf) (+ y ~1/inf))
The integer uses for EXPT should also be considered.
| there's nothing special about 0, as any function may impose
| relative trajectories for their arguments:
| (define (f x y) (/ x (* y y y (- y 1)))
| as such the only consistent thing that an implementation can
| warrant is that all primitive arithmetic expressions are
| evaluated equivalently about the static values passed to them,
| independently of whether or not the values passed to them have
| begun to loose precision due to the limited dynamic range of an
| implementation's number system. Thereby at least as a function's
| arguments begin to loose precision, the function correspondingly
| degrades in precision correspondingly and consistently, without
| after already yielding relatively inaccurate results decides it
| doesn't know the answer at all, or chooses to return a value
| which is inconsistent with it's previous results. (admittedly in
| my opinion)
SRFI-73 is about exact numbers. EXPT will only return exact numbers
for exact arguments. Loss of precision means inexact numbers.
| > (expt 0 0) ==> 1 is one of the possibilities for SRFI-70. But I
| > am leaning toward the "0/0 or signal an error" choice to catch
| > the rare coding error.
| - Again, in just my opinion, I'd rather a function return the most
| likely useful static value as a function of it's arguments, rather
| than it trying to pretend it knows something about the arguments
| passed to it and potentially generating a runtime fault.
| However it does seem potentially useful to be optionally warned
| whenever the precision of a primitive calculation drops below
| some minimal precision; i.e. it's likely much more useful to know
| when a floating point value is demoralized (as it means that the
| value now no longer has a represent-able reciprocal, or when an
| argument to an addition is less than the represented precision of
| the other operand, as these are the type of circumstances which
| result in inaccuracies, which by the time one may underflow to 0,
| or overflow to inf, and hope it gets trapped by some misguided
| function implementation which should have simply just returned
| the correct value based upon the arguments it was given and have
| the application check for what it believes is correct, it's
| already much too late, as regardless of whether some
| implementation's arithmetic system discontinuity was ticked, the
| results of a calculation are at best already suspect.
Bear@xxxxxxxxx is also interested in specifying precision. See
<http://srfi.schemers.org/srfi-70/mail-archive/msg00088.html> about an
idea for latent precisions.
| > | Where I understand that all inf's are not strictly equivalent,
| > | but when expressed as inexact values it seems more ideal to
| > | consider +-inf.0 to be equivalent to the bounds of the inexact
| > | representation number system, thereby +-inf.0 are simply
| > | treated as the greatest, and +-0.0 the smallest representable
| > | inexact value;
| > <http://srfi.schemers.org/srfi-70/srfi-70.html#6.2.2x> shows that
| > inexact real numbers correspond to intervals of the real number line.
| > Infinities corresponding to the remaining half-lines gives very clean
| > semantics for inexact real numbers. Infinitesimals (+-0.0) are a
| > solution in search of a problem.
| - only if it's not considered important that inexact infinities have
| corresponding reciprocals;
Inexact infinities have reciprocals: zero. Their reciprocals are not
unique, but that is already the case with IEEE-754 floating-point
179.76931348623151e306 ==> 179.76931348623151e306
179.76931348623157e306 ==> 179.76931348623157e306
(/ 179.76931348623151e306) ==> 5.562684646268003e-309
(/ 179.76931348623157e306) ==> 5.562684646268003e-309
| which seems clearly desirable as otherwise any expression which
| may overflow the dynamic range of the number system can't
| preserve the sign of it's corresponding infinitesimal value,
| which if not considered important, there's no reason to have
| signed infinities, either, etc. ?
#i+1/0 is the half-line beyond the largest floating-point value. The
projection of that interval through / is a small open interval
bordering 0.0. That interval overlaps the interval of floating-point
numbers closer to 0.0 than to any other. Thus the reciprocal of
#i+1/0 is 0.0.