niedziela, 20 listopada 2016

How not to compare floating point variables

During the introduction of floating point arithmetics my students often see a code like: Such an example is an occasion to explain the binary representation of floating point data and the problems with rounding errors.

Having in mind that floating point is not easy I am not eager to expose freshmen students to such problems specifically during tests and for a given problem:

Given the positive integer number x read from input, please print all numbers from [1..x] which are squares of natural numbers.

I have expected something like: But in one case I got something like (comment is mine): Beside efficiency issues, the above code is of course wrong. But, for some specific compiler, environment and small inputs it looked like working. To be honest, I was probably more surprised with this "correct" behavior than the student who was explained that the code is indeed wrong.

Comparing doubles by "==" operator is not a good idea but after several tests this example showed me that floating point arithmetic is less deterministic I had expected. For example it is not clear how much precision the internal calculations are evaluated at: double or maybe "register precision"? The answer is: "it depends", for more details I am redirecting you to Random ASCII, Floating-Point Determinism by Bruce Dawson and his earlier post: Intermediate Floating-Point Precision.

wtorek, 26 stycznia 2016

Even for simple code follow the rules as usually

The exercise was to write a my_find function in C++ using C style constructions known from standard qsort, bsearch like functions. The suggested prototype was:

void* my_find(void *key, void *array, int element_size, int n);
The key is a key we are about to find in the array of n elements where each element has the size element_size. The function should return the pointer to the element or null pointer if it does not exist. After over one hour, as an effect of a serious effort of one of my fairly good freshmen I got the following buggy code:

The problem is with the ArrayCOPY pointer which makes no progress with the iteration of outer loop in the case of false match.

Instead of correcting the above I would like to give similar code where the inner loop is a separate function thus making the whole thing easier to code:

Conclusion

The idea behind the student's solution was correct from the early beginning. The code seemed to be ready after approximately 15 minutes. Over next 40 minutes unsystematic (and unsuccessful) attempts were made to find and correct bugs. The point is: even if the task seems to be easy and straightforward, you need to keep calm and follow the rules (good programming practices) as usually.

wtorek, 8 grudnia 2015

C++ << operator evaluation order

Executing the code: with gcc compiler we receive:

 computing ... 
2 + 2 = 4
as expected. However, there is a pitfall as the behavior depends on the function parameter evaluation order. Let us investigate it in more details. First of all, the << operator is left-associative which means it is evaluated from left to right and the operator << is replaced with the equivalent function call (for more details and references please have a look at how does cout << actually work?). So, the line:
cout << "2 + 2 = " << foo() << endl;
might be seen as something like:
operator<<(operator<<(operator<<(cout, "2 + 2 = "), foo()),endl);
Now foo() is called before operator<<(cout, "2 + 2 = ") because of the right-to-left function parameter evaluation order. While the function parameter evaluation order is not defined by standard (again, see SO function parameter evaluation order question for more references), the code is in fact unsequenced and its behavior is undefined. Thus, it should be rather rewritten like:

Source details

The code comes from the simple console game where the foo() function was designed to execute the game itself and to return the game result to the main function of the program.