title: When long-double calculator loses its precision?
body: <p>My task was to write a code for a calculator that operates on <code>long double</code>. It turns out that after the certain point the calculator loses precision. For example it computes correctly <code>9999999 ^ 2</code>, but as far as <code>99999999 ^ 2</code> it yields the result, which is 1 bigger than it should be. I've already read something about the float precision, but all questions are concerned with decimals. I know that one can fix it by using the gmp library, but my question is: </p>
  
  <blockquote>
    <p>Is there any other way to tackle this problem?<br>
    How to calculate/show the point to which a long double calculator is accurate?</p>
  </blockquote>
  
  <p><strong>main.c</strong></p>
  
  <pre><code>int main(int argc, char *argv[])
  {
      char str[100];
      char key[] = "exit";
  
      if (argc &gt; 1)
      {
          switch (argv[1][1])
          {
              case 'V': case 'v':
                  setValid(1);
                  break;
              case 'E': case 'e':
                  setError(1);
                  break;
              default:
                  setValid(1);
                  break;
          }
      }
      else
          setValid(1);
  
      while (gets(str) != NULL &amp;&amp; strcmp(key, str) != 0)
      {
          if (calcFilter(str));
          else
              printf("expression error!\n");
      }
  
      return 0;
  }
  </code></pre>
  
  <p><strong>evalexpression.c</strong></p>
  
  <pre><code>static long double f1, f2;
  static char op;
  
  int isValidExpression(const char *str)
  {
      int res;
      char ops[10];
  
      res = sscanf(str, "%Lf %s %Lf", &amp;f1, ops, &amp;f2);
  
      if (res == 3 &amp;&amp; (ops[0] == '+' || ops[0] == '*' || ops[0] == '-' ||
          ops[0] == '/' || ops[0] == '^'))
      {
          op = ops[0];
          return 1;
      }
      else
          return 0;
  
  long double getExprValue(void)
  {
      switch (op)
      {
          case '+':
              return (f1+f2);
          case '*':
              return (f1*f2);
          case '-':
              return (f1-f2);
          case '/':
              return (f1/f2);
          case '^':
              return (pow(f1, f2));
          default:
              perror("something went wrong");
              return 0;
      }
  }
  </code></pre>
  
  <p><strong>calcfilter.c</strong></p>
  
  <pre><code>static int errorsw = 0, validsw = 0;
  
  int calcFilter(const char *str)
  {
      if (validsw == 1 &amp;&amp; isValidExpression(str))
      {
          printf("%s = %Lf\n", str, getExprValue());
          return 1;
      }
      else if (errorsw == 1 &amp;&amp; !isValidExpression(str))
      {
          printf("%s\n", str);
          return 1;
      }
      else if (errorsw)
          return 1;
      else
          return 0;
  }
  
  void setError(int mode)
  {
      errorsw = mode;
  }
  
  void setValid(int mode)
  {
      validsw = mode;
  }  
  </code></pre>