[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Zeroes and infinities



Thorsten Siebenborn wrote:
Peter Henderson wrote:
Thorsten Siebenborn wrote:
A rogue comment:
[...]

.
.
.
There are some general principles used in the standard that cover pretty well all cases for just about any real valued function of a real variable, at least in the default round-to-nearest mode. These principles require NaN^0 return NaN. In some cases, there is a feeling that an exception to these principles is more convenient or more intelligible. 0.0^0.0 = 1.0 is one of these cases.

What exactly yields the example of one case 0^0 == 1 in regard of
the question what NaN^0 should be ? And 0^0 == 1 is not just a
"feeling", it fulfills the valuable binominal theorem in case of 0.
The reason I became involved in these discussions was that I have strong objections to the the pow function as presented in David James' tables. The version presented in his table is modelled on the pow function in the C99 standard. My objection is that this function is a mish-mash of two functions that should be implemented separately.

Explicitly, there should be two functions with signatures powI: [-infty, +infty]x{the integers} -> [-infty, +infty] and powR: [0, +infty]x[-infty, +infty] -> [0, +infty]. powI just packages the usual integer exponentiation for which x^0 = 1.0 for all x in [-infty,infty]. This is the version relevent to the binomial theorem and powI(0.0, 0) = 1.0. powF is different, as there is no limit as (x,y) approaches (0.0, 0.0). Paths for x and y can be found yielding any limit in [0, +infty]. This is the function that I was referring to above and it is the proposal that powF(0.0, 0.0) = 1.0 that is generating some argument. My views on this particular case are not strong either way. As for powI(NaN, 0) and powF(NaN, 0.0), I feel strongly that both should return NaN, not 1.0.
.
.
.
But I am not talking about Infinity. I am talking about the result
of the *number* one divided by *number* zero. It seems to me that
you have substituted automatically "infinity" for 1/0 when I haven't
talked about the number "infinity" at all (I have said that 1/0 isn't
an infinity).
But IEEE 754 does, because in many cases it can be used to produce useful results, for example the straight-forward, fast and highly accurate evaluation of continued fractions, and it allows overflow and divide by zero to be indicated without having to check flags or causing a core dump. Generally, programmers don't attempt to calculate 1.0/0.0 out of the blue. Usually it sneaks up on them as a result of rounding error or underflow. If a function has a region where it is identically zero, then the programmer has to treat this carefully and 1.0/0.0 = infty is unlikely to be the correct response. But this is just part of understanding the problem at hand.
The IEEE standard takes the approach that infinity is the result of a limiting operation and the rules follow from the algebra of limit theorem for real-valued functions of several real variables.
.
.
.
Ah, you are substituting the numbers by limit operations, so in your
opinion IEEE 754 means effectively:
It is not just my opinion. A number of authors involved in the standards process have stated this explicitly. The only reference to this, that I have immediately to hand, is "What Every Computer Scientist Should Know About Floating Point Arithmetic". There is a pointer to it at http://grouper.ieee.org/groups/754. All the ideas I have presented in my post come from such sources.
f(-0.0) = lim f(x) for x->-0
f(0.0) = lim f(x) for x->+0
And that f(number) must therefore return NaN if the number has no
single limit ? Is that correct ?
Yes. But zero is a special case. You can deal with discontinuities at zero by assigning different values to f(-0) and f(+0). This is useful for functions such as the complex logarithm, where a discontinuity is unavoidable and the convention is to place it along the negative real axis.
Should you ever take a course in advanced theory of integration (usually called measure theory), among the first things
.
.
.
Well, I haven't taken a course in measure theory yet, probably
because I am too dumb for such complicated things,
I apologise for causing offence. It is so difficult to get the tone exactly right in these sort of forums. All I really meant was that if you need to study certain areas, you will find that infinity is invoked, and in addition, the rules of infinity arithmetic differ from application to application.
.
.
.
One thing -- in school I learned that numbers are
something like "fields", containing an inverse element for
multiplication and therefore the operation of division. Are these new
extended real numbers fields, too ? Is therefore
the operation "/" comparable with the operation division in a field ?
Where an arithmetic is defined for infinity, the attempt is usually made to preserve as many of the usual rules as possible. Most commonly what is lost is closure. i.e. not all combinations of operands produce a defined result. IEEE arithmetic uses the algebra of limits theorem to guide the manner in which the arithmetic is extended from the reals to +/-infty. Hence 0/0 is not defined, since for any y in [-infty, +infty], we can find functions f(x) and g(x) that tend to zero as x tends to 1 say, such that f(x)/g(x) tends to y. In the example from integration theory, unlike IEEE arithmetic, 0*infty=0 and x*0=0 for all x in [-infty,+infty].
While FP numbers are crude approximations of the fields R and C
(not obeying the distributive law), they are intended to model them,
right ?
Not exactly. FP numbers are exact representations of real numbers. It is the floating point operations +, -, / and * that are approximations of their counterparts from the real number system, just as any floating point evaluation of a function is an approximation of the actual real value.
.
.
.
When the original IEEE 754 standard was being written, there was a proposal by Fraley and Walther, to have special overflow and underflow symbols. It is described in "Analysis of Proposals for the Floating-Point Standard", W. J. Cody, Computer, pp,. 63--68, v. 14, no. 3 March, 1981. Presumably the actual proposal is given in ACM SIGNUM Newsletter, special issue on the Proposed IEEE Floating-Point Standard, October 1979.

Thank you. Another member already pointed out the idea of Fraley
and Walther, but didn't know when or where it was publicized.
I have not actually set eyes on it, but the I'm pretty sure the exact reference is: R. Fraley and S. Walther, "Proposal to Eliminate Denormalised Numbers", ACM SIGNUM Newsletter, pp. 22--23, No. si-2, v. 14 (October, 1979). It is available through the ACM portal. Unfortunately you need to be a subscriber. I am not, which is why I have not read it.
.
.
.
I doubt that the infinities or signed zeros are in any case better
suited or easier to understand than ov's and un's. The payoff between
rise of complexity and advantages may be a valid counterargument,
In many ways, the IEEE 754 system is the case of ov's and un's reduced to their simplest form. I don't see the IEEE approach as particulary complicated. The flaw is that there is a relucance to express the principles behind it explicitly in the standard. The algebra of limits theorem(s), on which these principles are based, is widely taught early in college mathematics.
I translate:
You think that I think that FP numbers are intervals.
I actually wasn't thinking that as such. However, in this context, this idea is closely related to the idea of invoking infinitessimals.
But the "only
interpretation that works" is that every FP number represents itself
This is necessary to allow you to define what the results of the floating point operations should be. For example, the result of floating point addition is the result of real addition of the floating point operands after rounding. The big feature of the original IEEE standard was that it insisted that this be done properly.
when you already mentioned that infinity is a result of a
limiting operation.
The difficulty here is we are starting to head into real philosophy, i.e. what are numbers? Infinity is a value appended to the real numbers. We use a limiting process to determine what value should result from using infinity as an operand.
A few lines later you suddenly tell us that for +0/-0 a "partial exception" must be made because in that case the "only working interpretation" ceases to function.
No, it has to be extended, as part of the procedure of extending the reals to include infinity.
You are also
claiming that both values represent zero and that they
should compare equal.
That is what the standard intends.
But you are *also* claiming that they are in fact limits
according to the direction the variable uses because it is the
only reason how the use of 1/+0 and 1/-0 with different results
can be explained.
I am not saying they are limits. The IEEE standard defines addition, subtraction, multiplication and division tables for the set of floating point numbers, together with infinity and with signed zero. But such tables would be of little interest if there was not a strong mathematical motivation for them. For the ordinary floating point numbers, it is the standard definition of these operations. For the special values, it is provided by the algebra of limit theorem.
In fact you have summarized all the problems
I encounter with signed zeroes
.
.
.
- There is only one value *zero* and besides that plus and minus zero
  *cannot* both represent the same number because they violate the
  fundamental identity that for x == y => f(x) == f(y)).
In the case x and y are not zero, this identity holds, as no attempt is made to indicate the direction from which x is approached. For x and y zero, perhaps with different signs, this identity still holds, provided f is continuous at x. If a function appearing in a program has a discontinuity, then any calculations near the discontinuity need to be treated with considerable care. The difficulties arise not because zero has a sign, but because the function is discontinuous. The programmer has to think about what to do in this situation. Often, there is a preferred definition of the function at the point of discontinuity, but this is merely a convention, and only some of the time is it the right choice for a particular application. For example, with the complex logarithm, the principle value of ln(-1) is conventionally pi. But if you have an application where im(z) <= 0 when re(z) < 0, then the proper value to use for ln(-1) is nearly always -pi. On the other hand, with this example, if the next operation is exp(z), the value chosen doesn't matter, as exp(z) is blind to the difference.

One of the cases where the sign of zero is important is when using the copysign function. copysign(x, -0) = -|x| and copysign(x, +0) = |x|. But this just illustrates my point. No matter how someone chooses to define this function, there will be a discontinuity at zero, and know choice will be appropriate for every application. The IEEE version has the advantage that it will often give the desired result since zeros often arise due to underflow, and so when this occurs, copysign delivers the result as if underflow had not occurred. N.B. underflow can only occur as a result of multiplication or division.
  If one of them is "zero", what does the other one represent and why
  on earth are they compared as equal ?
The point is the distinction is invisible to the ordinary floating point numbers.
.
.
.
Together with the alliance to eradicate flags and traps
Traps and flags have been a feature of hardware since very early on, but language designers and hardware designers hate them. Language designers hate them because they have global effects that completely ignore any scoping rules, are difficult to fit into the underlying models on which most languages are based and can unpredictably break the flow of a program. Designers of high performance hardware hate them because they can impose strict constraints on the order in which otherwise unrelated events occur and can cause already started operations to abort, requiring complicated unwinding of partially completed operations.
it may cause strange and irregular
  sign problems (if the +-infinity is eradicated in a denominator).
  And that is not a freak-case; it was the very reason I stumbled
  over the signed zero because my program (Java) did exactly this.
It sounds like you gripes might be more with Java, than with the IEEE standard floating-point.
If the sign of zero bothers you, ignore it. It will only cause you problems if an overflow occurs and does not resolve itself, in which case you will end up with +/-infty or NaN, or if you use copysign, in which case you should be paying more attention anyway.
The point is, for debugging the programmer should probably enable the overflow and divide by zero traps. The default trap handlers usually start a debugger (Microsoft Windows), or cause a core dump, that can be read in by a debugger (Linux). This way he/she can find where the problems occur. Where overflows or divide-by-zero are a problem (usually as a result of underflow), the program can test the results for infinity or NaN, and take appropriate action. This is far simpler than trying to determine if these conditions will occur before the operation is performed. Of course, the first step is to try and anticipate the problems ahead of time.
Of course, I am assuming you are not a compiler writer, a floating-point hardware designer, a library routine author or a standards committee member.
Of course I assume you are a standards committee member?
No I am not. You have misunderstood my intent. I meant ordinary programmers can ignore these issues. Of course they can't ignore overflows or divide-by-zero, but then, this has always been the case, even when zero did not have a sign and infinity was not available. Compiler writers and hardware designers have a responsibility to implement the standard correctly. Of course, standards committee members also have to understand these things. As for library routine authors, using these facilities allows them to write faster code that produces more accurate results and handles everything thrown at it.

Regards,
Peter Henderson

754 | revision | FAQ | references | list archive