1

I have a multiline file. First line contains an integer N, followed by exactly N lines, where each of them contains a pair of floats seperated by a white space. Each float has exactly two decimal digits. Now i have the following simple code, which stores the floats in memory and prints them.

    #include <stdio.h>
    #include <stdlib.h>

    struct coordinates {
         float x;
         float y;
    };

    typedef struct coordinates coords;

    int main(int argc, char** argv) {
      unsigned int N, i;
      coords *points;
      FILE *fp;

      if (argc != 2) {
          printf("Usage: ./bigCircle <input_file>\n");
          exit(0);
      }
      fp = fopen(argv[1], "r");
      N = fscanf(fp, "%u", &N);

      points = (coords *)malloc(N*sizeof(coords));
      for (i=0; i<N; i++) {
          fscanf(fp, "%f %f", &points[i].x, &points[i].y);
          printf("%f %f\n", points[i].x, points[i].y);
      }

      return 0;
   }

The problem is that the floats printed have far more non-zero decimal digits and become the right ones only when rounded to the second decimal place. For example, for the pair

  99999.72 -50167.43

my program prints

  99999.718750 -50167.429688

Why is this happening? Why don't i get

  99999.720000 -50167.430000

?

blaze9
  • 89
  • 1
  • 9

4 Answers4

1

Once the number is put into the location in binary floating point format, it is digitized. Your computer cannot represent this number exactly. As a result, the output is not exactly the number that you entered.

Your output "%f" does not specify the two decimal digits as the limit. Thus, when it tries to output the value that you have read in, it will have more digits output.

As an example consider the number 1.3. The number to the right of the decimal point, since it is a decimal number, cannot be expressed exactly in binary format. Since you have seen that in your examples, try to convert .5 (decimal) to binary (which is .1).

As an example consider the value 1/8 (2^-3) This is 0.1 in octal. However, it is .125 in decimal and .001 in binary. It can be expressed exactly because it is an integer power of 2. Unless a number can be expressed as a sum of a finite number of powers of 2, it can never be expressed exactly in a computer.

sabbahillel
  • 4,357
  • 1
  • 19
  • 36
1

This is a very simple - it is a matter of what numbers the format can encode.

Consider an integer. It can represent values like 0, 1, 2, ...

But it can't represent numbers like 1.2, 3.4, ...

The same is true for floats! It just can't represent all numbers.

For instance: 99999.72 might not be accurately encoded so the nearest value (maybe 99999.718750) is what you end up with.

So the numbers will be rounded to the nearest representable number.

Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
1

A float is represented internally as a binary floating point number. When we represent a number in base 10 we have something like:

1.625 = 1 + 6/10 + 2/100 + 5/1000

for a number that can be represented exactly in base 10 notation. Then, in binary we can represent the same number as:

1.625(base 10) = 1 + 1/2 + 0/4 + 1/8 => 1.101(base 2)

So, here we have an exact binary representation for this number. But, some numbers that have exact representations in base 10 do not have exact representations as floats, because the internal representation is binary:

1.72(base 10) = 1 + 7/10 + 2/100, but

1.72(base 10) = 1 + 1/2 + 0/4 + 1/8 + 1/16 + 1/32 + 0/64
               + 0/128 + 0/256 + 0/512 + 1/1024 + ...

The last partial sum gives:

1.1011100001(base 2) => 1.71972656(base 10) != 1.72.

So, the exact binary representation may be to large to fit in the available storage, or there may be no exact binary representation!

Incidentally, 1.10111(base 2) => 1.71875(base 10). Given that you saw 99999.718750 instead of 99999.72, I would guess that you have 8 bits available for the fractional part of your float.

ad absurdum
  • 19,498
  • 5
  • 37
  • 60
0

Try to replace:

printf("%f %f\n", points[i].x, points[i].y);

with that:

printf("%.2f %.2f\n", points[i].x, points[i].y);

With the above, you tell to printf to print the first. X decimal digits of the real number.(in our case 2). The first one prints the whole float number

jrbedard
  • 3,662
  • 5
  • 30
  • 34
Jim_Spr
  • 21
  • 4