Precise math division

Asked

Viewed 3,125 times

56

In Windows calculator: 9/3,0001 = 2,999...
In my program: 9/3,0001 = 3;

I would like to get that level of accuracy using C.

Watch excerpts from my program:

double op(double num1, double num2, char c)
{
      if(c == '/')
      {
        if(num2 == 0)
        {
            printf("operacao nao pode ser realizada");

            exit(1);
        }
        else
            num1 = (num1)/num2;
      }

      ...

      printf("%.3lf\n", num1);

      return num1;
}

int main()
{
   double num1,num2;

   char c;

   scanf("%lf", &num1);

   scanf("%lf", &num2);

   scanf(" %c", &c);

   num1 = op(num1, num2, c);

   ...

   return 0;
}

How to do?

  • -1. #QNAN0 error is Negative Quiet Not a Number

4 answers

35


If you really want exact accuracy for floating point operations, you will need to use a library such as the GMP. User @Maniero gave a reasonable introduction on where to find more information about floating point (which is not a problem of the C language itself, but the way floating point is implemented within the processor).

The GMP library, from GNU Multi-precision Library, is a library open source, to work with numbers with arbitrary precision, whether integer, fractional or floating-point.

It’s very simple to work with, and the documentation is quite complete, and the library is available for all major platforms and architectures.

More information on The GNU Multiple Precision Arithmetic Library.

  • 1

    I was looking for her :)

33

There are several posts about it here on the website (this for example). You can’t do this in any number language with binary floating point which is the case of float and double. You need to assemble a data structure or treat the data in a different way. Usually it’s the way decimal or monetary. Commonly the numbers are treated as if they were integer and presented with homes after the comma.

The precision achieved with binary floating point has small flaws that are well accepted in many situations and works with the advantage of being extremely fast. One of the situations where it cannot be used is when monetary values are being used. But any case where absolute accuracy is required.

There is nothing to solve the floating point "problem". You can use a die with many decimal places of precision that will not solve the question.

In English (the best references on the subject):

These responses are not specific to C but the concept is the same for all languages because it is the way the processor works.

Any other way will only create an illusion that the division was done correctly.

The Windows calculator solves the issue in its programming. The software understands that accuracy is needed and handles the data in this way. Interesting fact: Divide 10 by 3 and then multiply the result by 3 in the Windows calculator. Then clean everything and type the split result in hand. Can for as many houses as you want in tithing. (3.33333333333333). Multiplication by 3 gives different result. The software controls this.

  • 7

    Wow, it seemed like a simple question, there’s an ocean behind it.

  • Very interesting, obg!

20

In your example, 9/3.0001 ~ 2.99990000333322222592

Thus, the round answer to 3 decimal places is in fact 3,000. Your program is correct, within the limits of precision you specified. If you want the result with more precision boxes, you should indicate it in printf:

printf("%.9lf", num1);  // com 9 casas de precisao

The double type is accurate enough for about 15 significant digits (it does not mean that it is 15 decimal places, it depends on how many significant digits you have in the whole part of the number). If you really need more than that, then you can use another type of representation, as suggested.

For scientific calculus (in engineering, physics, other experimental sciences) it is usual to use floating-point representations (such as the double) because the data itself is generally inaccurate. Thus, the results calculated from these data also cannot be very accurate. If you took a measure of length using a ruler with a resolution of 1 tenth of a mm, then the observed measure of 3,0001 m may actually be 3,00013 m or 3,000098. The observation has an error that can be +/-0.00005 m. If you divide two measures with this margin of error, the result is also affected by an error of the same order of magnitude. Thus, it is not significant to show the result with more significant numbers than it has in operands.

In many applications, it is rare to have data with more than a dozen significant digits, so the accuracy of a double is usually more than enough.

8

If you at all times whether exact numerical results, this is intrinsically impossible to achieve using computers or not. For example, what is the "exact" result of the square root of 2 ? The result is an irrational number, so it has no numerical representation exact. There are many other numbers like this, an infinite number actually. : ) (There are even rational numbers of infinite size, which are the periodic tithes.)

Specifically for computers, even for rational numbers it is not always possible to obtain an "exact" numerical representation. Just think of a big number, for example 1234567890[5 repetitions]. Cannot represent this number accurately in a variable double of the language C, simply because it does not fit in a variable double...

To my knowledge, there are (at least) three ways to partially circumvent the mathematical limitations of current computers and languages.

The first way is to use a mathematical library of "infinite precision". These libraries are widely used today because they are required for computational cryptography (mainly public key cryptography, used in "secure connections" on such websites https://). Obviously these libraries continue to have limitations in numerical representation of irrational numbers, but use a method for storing numbers that makes it possible to calculate with "large" numbers, such as 1234567890[5 repetitions] which I quoted above, or as 1024 or 2048 bit keys widely used in public key cryptography.

The second way is to work with fractional number library. In this way, it is possible to work naturally with periodic tithes and with certain types of irrational numbers.

The other way is to work with symbolic mathematics, where symbols are used for known irrational numbers, like e, pi, etc. Usually you use some specific application for this, like "Wolfram Mathematica" (and similar open source programs), or specific languages, as (if I’m not mistaken) R, Julia, etc. Surely there are also libraries for symbolic mathematics for bindings like C, Python, etc., it’s just a matter of searching.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.