简体   繁体   中英

Understanding floating point variables and operators in c++ (Also a possible book error)

I am working through a beginning C++ class and my book(Starting Out with C++ Early Objects 7th edition) has a very poor example of how to check the value of a floating point variable.

The book example in question(filename pr4-04.cpp):

// This program demonstrates how to safely test a floating-point number
// to see if it is, for all practical purposes, equal to some value.
#include <iostream>
#include <cmath>
using namespace std;

int main()
{
    double result = .666667 * 6.0; 

    // 2/3 of 6 should be 4 and, if you print result, 4 is displayed.
    cout << "result = " << result << endl;

    // However, internally result is NOT precisely equal to 4.
    // So test to see if it is "close" to 4.
    if (abs(result - 4.0 < .0001))
        cout << "result DOES equal 4!" << endl;
    else
        cout << "result DOES NOT equal 4!" << endl;

return 0;
}

And I use g++ in Ubuntu to compile my code like this:

g++ pr4-04.cpp -o pr4-04 && ./pr4-04

And I get this error:

error: call of overloaded ‘abs(bool)’ is ambiguous

I am able to fix this by changing abs() to fabs(), but this is still super confusing! Why is the book giving us things which won't compile, or is this just me? Why does the cout of 'result' give 4 instead of 4.000002? Why does this value seem to change when it is used in the if{} statement?

I get that we can't just use == to check for equivalence, but why do I need to use the absolute value? I get the same answer whether or not I use it. So what is the point?

Not to mention, this seems like a very poor way to check for floating point equivalence. Is there a better way to do this? This topic seems awfully important .

I found this topic here on stackoverflow, but their solution:

fabs(f1 - f2) < precision-requirement
fabs(f1 - f2) < max(fabs(f1), fabs(f2)) * percentage-precision-requirement

Doesn't make much sense to me in the context of my 4 chapters worth of C++ experience. I would greatly appreciate some help. Our book has given me a whopping 6 sentences of text to explain all of this.

Edit: As suggested by some I tried to find an errata page, but after 30mins of searching the textbook, internet, and my course website I was only able to find this downloadable zip file , which required a login -_-

I also copied the code perfectly. That was not MY typo, I copied it directly from a CD with the code on it. It is also typed that way in the book.

if (abs(result - 4.0 < .0001))

The parenthesis are wrong, you probably mean: if (abs(result-4.0) < .0001) .

As to why it did not compile, the standard determines in §26.8p8 that

In addition to the double versions of the math functions in , C++ adds float and long double overloaded versions of these functions, with the same semantics.

The expression (result-4.0 < .0001) yields a bool , and there is no overload of abs that takes a bool argument, but there are multiple versions of abs for which the argument is implicitly convertible from bool . The compiler does not find one of the conversion sequences better than the rest and bails out with the ambiguity error.

The problem is clearly the line

if (abs(result - 4.0 < .0001))

which should be written as

if (abs(result - 4.0) < .0001)

I would assume that this is a simple typo. Report the error to the author of the book!

BTW, the original code does compile on my system without any problem, giving the expected result! That is, even if the author tested the code he may not have noticed that it is problematic!

Also answering the question on why abs() is needed: some decimal numbers are rounded to a floating point value which is slightly smaller than the expected result while others are rounded to number which are slightly bigger. In which direction the values are round (if at all: some decimal numbers can be represented exactly using binary floating points) is somewhat hard to predict. Thus, the result may be slightly bigger or slightly smaller than the expectation and the difference, thus, positive or negative, respectively.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM