in reply to Re^3: [Win32, C, and way OT] C floats, doubles, and their equivalence
in thread [Win32, C, and way OT] C floats, doubles, and their equivalence

I don't know that that is a reasonable expectation

Yes, I don't know if it's reasonable, either - but it does appear to be reliable except when a pre-VC8 MS Compiler is being used.

In general, exact equalities on doubles and floats is not a good idea. I'm a little surprised that PDL code is assuming that it is

No - that assumption is not being made ... well, not explicitly, anyway. The exact problem I'm looking at is not all that complex:

Basically, if you have a piddle (array) of values, you should be able to call setvaltobad(123), and every occurrence of 123 in that piddle will be changed to 'BAD'. So, if we have a piddle of floats [1/3, 2/3, 1, 4/3] and we call setvaltobad(2/3), then that piddle should become [1/3, BAD, 1, 4/3]. And that's exactly what happens ... unless we're using one of those older Microsoft Comnpilers (in which case the piddle remains unchanged).
Now, part of the problem is probably that setvaltobad(2/3) passes a double (NV). But that's not a problem with any compiler other than the ones I've already specified (afaik).

It's the sort of thing that probably won't ever affect anyone ... but there's a test for this in the current test suite, that test fails when PDL is built with one of the older Microsoft Compilers, and it would be nice to fix that failure without having to go to too much trouble.

(Unfortunately, it has already become "too much trouble" :-)

Cheers,
Rob

Replies are listed 'Best First'.
Re^5: [Win32, C, and way OT] C floats, doubles, and their equivalence
by repellent (Priest) on Jul 20, 2009 at 23:27 UTC
      Yes, I don't know if it's reasonable, either - but it does appear to be reliable except when a pre-VC8 MS Compiler is being used.

    You may find that reliability short-lived. I'm with ELISHEVA. The two formal ways of comparing floats/doubles are (coded in Perl, but same idea):
    # absolute error method $is_within_tolerance = abs($value - $expected) < EPSILON; # relative error method - $tolerance_error should be within threshold +percentage $tolerance_error = abs(($value - $expected) / $expected);

    Crazy suggestion: You could write a function redofloat() that sprintf "%.15f" the number and then converts the resulting string back to a float/double. The idea here is to truncate each number's least significant bits that differ, caused by the division operations. Faster, if you can mask those bits off directly (but then you'd have to worry about portability).

    Then: redofloat(foo) == redofloat(nv)
      You may find that reliability short-lived.

      Could be - I find in Kernighan & Ritchie:
      "When double is converted to float, whether the value is rounded or truncated is implementation-dependent."
      That would appear to open the door to the possibility that we *can* do float f = X; double d = X; and still have f != (float)d (for some value/expression X).

      The two formal ways of comparing floats/doubles are ...

      Yes, and those are good ways - but I'm looking at comparing a float and a double that have been assigned the same value/expression.

      Still, now that I've found that statement in K & R, I'll see if anyone on the PDL list sees any cause for concern. My hunch is that the current method will stand until someone reports a breakage. I guess I could report a breakage on the basis of my experience with VC 7.0, but that breakage was just straight out compiler flakiness - nothing to do with the "implementation-dependent" behaviour alluded to by K & R.

      Cheers,
      Rob

      UPDATE: I think the way PDL is handling these values is fine. Afaict, pdl(float, 2/3) will assign exactly the same value as used by setvaltobad(2/3)
      In both cases the value is (double)2/3 cast to a float, so behaviour will be as desired, irrespective of the way the compiler implements the cast from double to float.