2

Is it guaranteed of floating point that:

  • (a <= b) implies !(b > a)
  • !(a <= b) implies b > a

I'm dealing cross-language at the moment, but you can assume a float or double in one of C, C++, or C# if necessary. Assume no NaN is involved.

I assume the rules of IEEE apply here. I'm uncertain if their ordering rules imply the above.

My particular concern is that a and b aren't always the same variable, but will be the same value. They always result from exactly the same calculation. However, since the comparisons are done in different code locations I can't guarantee if they are always the stored/truncated forms (one may end up with extended precision).

As I'm looking for guarantees the answer should include references which make those guarantees, or officialy/strongly imply the guarantees.

edA-qa mort-ora-y
  • 30,295
  • 39
  • 137
  • 267
  • What about assumptions of infinity and +-0? – James Snook Mar 04 '15 at 08:27
  • @JamesSnook, none. The values could be +-Infinity or +-0. Though you can ignore the +/-0 if it makes it easier. The values are generated in the same fashion each time, so they will not fluctuate between +-0. – edA-qa mort-ora-y Mar 04 '15 at 08:28
  • 1
    The assumption that the rules of IEEE 754 apply is a dangerous one. Some languages, including C, C++, and C#, allow the compiler to arbitrarily use higher precision for some calculations. The results of two calculations could be equal if both results are rounded down to 64-bit, but unequal if the comparison is done in an 80-bit extended format. – Patricia Shanahan Mar 04 '15 at 10:34
  • There are guarantees in all kinds of standards here, but those guarantees are routinely violated by compilers. I would refer you to [gcc bug 323](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=323), but it appears you have known about this for more than 10 years. – tmyklebu Mar 05 '15 at 04:10
  • @tmyklebu I guess I always secretly hope that floating point has somehow gotten easier and more sane over time. I guess the question is only answerable with truncated floats. It's too bad that langauges have yet to provide a way to guarantee truncation. There should be IEEE-exact semantics available for when you need them. – edA-qa mort-ora-y Mar 05 '15 at 05:14
  • 1
    @PatriciaShanahan If `__STDC_IEC_559__` is defined, the compiler promises IEEE-754 floating-point arithmetic is in effect. That doesn't mean it doesn't have bugs however. Furthermore, what you just said isn't quite true; The compiler can do math in arbitrary precision, but by the as-if rule, any excess precision must be rounded off. That this isn't done sometimes, or only done when a register spill is needed, is a bug that was explored in the paper [The pitfalls of verifying floating-point computations](https://hal.inria.fr/file/index/docid/182252/filename/floating-point-article.pdf). – Iwillnotexist Idonotexist Mar 05 '15 at 13:44

2 Answers2

6

According to the IEEE 754 (2008) standard (§ 5.11):

Four mutually exclusive relations are possible: less than, equal, greater than, and unordered. The last case arises when at least one operand is NaN. Every NaN shall compare unordered with everything, including itself. Comparisons shall ignore the sign of zero (so +0 = −0). Infinite operands of the same sign shall compare equal.

So yes, assuming neither argument is a NaN, then both of those statements are correct.

As to the use of implicit extended precision formats, the problem is that allowing these means that it's no longer strictly following the IEEE 754 standard. See this excellent answer and discussion on enabling strict compliance.

UPDATE: as I understand it, if you're using a recentish standard (e.g. -std=c99) then you don't have to worry about intermediate precision as long as the things you're comparing are declared variables (e.g. double a = 0.1; if (a < b) ...) and not constants (e.g. if (0.1 < b) ...).

Community
  • 1
  • 1
Simon Byrne
  • 7,694
  • 1
  • 26
  • 50
  • 1
    I guess with extended precision they aren't guaranteed then. Using very low precision as a guide. `5.5 > 5.4` but `!(5 > 5)`. I guess I have to force a truncation on my numbers somehow. – edA-qa mort-ora-y Mar 04 '15 at 11:56
3

The answer is yes, but only because you exclude NaNs, by my reading of the IEEE-754 Standard. Normally the answer is no. The relevant chunk of the Standard reads as follows:

5.11 Details of comparison predicates

For every supported arithmetic format, it shall be possible to compare one floating-point datum to another in that format (see 5.6.1). Additionally, floating-point data represented in different formats shall be comparable as long as the operands’ formats have the same radix.

Four mutually exclusive relations are possible: less than, equal, greater than, and unordered. The last case arises when at least one operand is NaN. Every NaN shall compare unordered with everything, including itself. Comparisons shall ignore the sign of zero (so +0 = −0). Infinite operands of the same sign shall compare equal.

Languages define how the result of a comparison shall be delivered, in one of two ways: either as a relation identifying one of the four relations listed above, or as a true-false response to a predicate that names the specific comparison desired.

Table 5.1, Table 5.2, and Table 5.3 exhibit twenty-two functionally distinct useful predicates and negations with various ad-hoc and traditional names and symbols. Each predicate is true if any of its indicated relations is true. The relation “?” indicates an unordered relation. Table 5.2 lists five unordered-signaling predicates and their negations that cause an invalid operation exception when the relation is unordered. That invalid operation exception defends against unexpected quiet NaNs arising in programs written using the standard predicates {<, <=, >=, >} and their negations, without considering the possibility of a quiet NaN operand. Programs that explicitly take account of the possibility of quiet NaN operands may use the unordered-quiet predicates in Table 5.3 which do not signal such an invalid operation exception.

Comparisons never signal an exception other than the invalid operation exception.

Note that predicates come in pairs, each a logical negation of the other; applying a prefix such as NOT to negate a predicate in Table 5.1, Table 5.2, and Table 5.3 reverses the true/false sense of its associated entries, but does not change whether unordered relations cause an invalid operation exception.

The unordered-quiet predicates in Table 5.1 do not signal an exception on quiet NaN operands:

Table 5.1—Required unordered-quiet predicate and negation

enter image description here

The unordered-signaling predicates in Table 5.2, intended for use by programs not written to take into account the possibility of NaN operands, signal an invalid operation exception on quiet NaN operands:

Table 5.2—Required unordered-signalling predicates and negations

enter image description here

The unordered-quiet predicates in Table 5.3, intended for use by programs written to take into account the possibility of NaN operands, do not signal an exception on quiet NaN operands:

Table 5.3—Required unordered-quiet predicates and negations

enter image description here

There are two ways to write the logical negation of a predicate, one using NOT explicitly and the other reversing the relational operator. Thus in programs written without considering the possibility of a NaN operand, the logical negation of the unordered-signaling predicate (X < Y) is just the unordered-signaling predicate NOT(X < Y); the unordered-quiet reversed predicate (X ?>= Y) is different in that it does not signal an invalid operation exception when X and Y are unordered (unless X or Y is a signaling NaN). In contrast, the logical negation of (X = Y) might be written as either NOT(X = Y) or (X ?<> Y); in this case both expressions are functionally equivalent to (X ≠ Y).

To me, therefore, since the UN relation is excluded by the absence of NaNs, it follows that what remains is the set EQ LT GT. Affirming LT EQ implies denying GT, and denying LT EQ is indeed GT.

Community
  • 1
  • 1
Iwillnotexist Idonotexist
  • 13,297
  • 4
  • 43
  • 66