Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

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

by ELISHEVA (Prior)
on Jul 18, 2009 at 19:03 UTC ( [id://781372]=note: print w/replies, xml ) Need Help??


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

Similarly, if I have: float x = 123.1; double y = 123.1; then I expect x == (float)y to be true

I don't know that that is a reasonable expectation. Conversion from double to float is not the exact same operation as the initial assignment. The first is converting the numeric string to a floating point representation. The resulting floating point representation will be very very close to but not necessarily exactly "123.1" or whatever other value you assign to it. By contrast converting double to float is reducing the number of significant digits in a representation that is already approximate. Mismatches between assignment and rounding are always possible.

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. I was always taught instead to do x - y < EPSILON where EPSILON is some value small enough to make the difference between the two numbers irrelevant for the purposes of your computation. If exact decimal precision is needed (as is sometimes the case in financial calculations) then one needs to use one of the many C/C++ arbitrary precision libraries.

Best, beth

Update: x - y < EPSILON assumes it is known that x >= y (i.e. prior code has tested that assertion). In the general case where that assertion has not been verified, see comment by roboticus below.

Replies are listed 'Best First'.
Re^4: [Win32, C, and way OT] C floats, doubles, and their equivalence
by syphilis (Archbishop) on Jul 19, 2009 at 01:34 UTC
    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
        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.
Re^4: [Win32, C, and way OT] C floats, doubles, and their equivalence
by roboticus (Chancellor) on Jul 19, 2009 at 10:24 UTC
    ELISHEVA:

    Minor correction: fabs(x - y) < EPSILON to catch the case where y is greater than x.

    ...roboticus

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://781372]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (2)
As of 2024-04-25 18:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found