I solve various kinds of Olympiad problems, when I worked in Pascal I never thought about the work of the operator "=" or "> =" in working with real numbers, I thought that with the accuracy of comparisons and problems there could not be. But I switched to C ++ and one teacher told me that "==" or "> =" cannot be used when working with real numbers in C, you need to write fabs(a - b) > eps . And here is the question:

  1. Is it true?
  2. How to choose the right eps?
  3. And why could some tasks not pass all the tests with such a chip, and when I wrote simply "==" they passed.

Here is a specific example. The task that passed after I changed LessEqual to "<=". Given a real number a and a natural n. Calculate the nth root of a. The program should display a single number: the answer to the problem with an accuracy of at least 6 decimal places

 #include <cstdio> #include <iostream> #include <cmath> using namespace std; const double eps = 1e-8; const double eps2 = 1e-12; bool Equal(double a, double b) { return fabs(a - b) < eps2; } bool lessEqual(double a, double b) { return ((a < b) || Equal(a, b)); } double a; int n; void solve() { double l = 0, r = a + 1, mid = 0; while (r - l > eps) { mid = (l + r) / 2; if (lessEqual(pow(mid, n), a)) l = mid; else r = mid; } printf("%.7lf", l); } int main() { freopen("input.txt", "r", stdin); freopen("output.txt", "w", stdout); scanf("%lf\n", &a); scanf("%d", &n); solve(); return 0; } 
  • four
    Do not worry, you have moved to a new level of complexity. Soon you will have a level up :) - jmu
  • one
    In Pascal, the rules of the game are exactly the same, because sooner or later it all comes up against IEEE754 ( en.wikipedia.org/wiki/IEEE_floating_point ) - Kromster

5 answers 5

Really nothing good will come out of a comparison of the type == in operations with real numbers. You can try simple code:

 double sum = 0; for ( int i = 0; i++; i < 1000000000 ) { sum += 0.000000001 } 

To guarantee that the sum will be equal to 1 in this case is impossible. Maybe equal, maybe not. The point is machine precision rounding mat. operations. And your teacher says it right. Comparison of the form

 fabs ( 1.0 - sum ) < 0.0000000000000001; 

It will always give the correct result. ps I took the number 0.0000000000000001 just like that, but believe me, this calculation error is very small, but still you will not get an accurate result (sum == 1.0)

    The problem here is not the "inaccurate" comparison of the processor hardware, but the fact that some decimal fractions cannot be accurately converted to binary floating-point format.

    Another problem is the loss of the lower digits of the mantissa during calculations in cycles.

      1. In response to the development of the distinguished @AVP . If the task allows, convert your numbers to fractions that can be represented as a binary fraction: not 0.1, but, for example, 25/256, etc. This will protect your cycles from non-revenue or exceeding the specified value of the constant cycle.
      2. In C ++, the epsilon constant you are interested in is defined in the float.h library - DBL_EPSILON. Look at its value for your compiler.
      3. Comparing "> =" is always valid.
        1. Not quite right.
        2. eps depends on how accurately you want to calculate certain indicators. Typically, the accuracy is indicated when setting the problem. For example: Calculate up to the seventh decimal place, then eps = 0.0000001
        3. It's not clear, you need to watch the tasks.

        In general, accuracy is a rather conventional concept, as can be seen from the formula fabs (a - b)> eps, and it will vary from task to task.

          In fact, in real life it is impossible, for example, to say that two sticks are equal in length, it can be said that their lengths differ by a very small amount, i.e. | length1-length2 | <eps. Since floating-point numbers are used to model real ("real") values, they should be treated accordingly.

          To the question of how to choose eps. For sticks, 1 cm may be enough, for some parts - 0.5 mm. And if in the task it is said, for example, to count with an accuracy of up to 6 decimal places, then eps is taken equal to 1E-6 (that is, 10 to -6 degrees).

          • Not certainly in that way. If two floating-point numbers are obtained by the same calculations (a sequence of commands with the same initial data), then they will be equal . If we calculate them by "slightly different" algorithms, they may differ. - avp
          • one
            [Except if these numbers were obtained by the same calculations on Pentium processors] [1] [1]: en.wikipedia.org/wiki/Pentium_FDIV_bug - gecube
          • @avp, yes, technically can be equal, but in practice the coincidence of real numbers to the last binary decimal place is usually not required. - insolor