简体   繁体   中英

Why does my string to float conversion function return a number that's slightly off in pure C?

I made a program to convert strings into floats, but its slightly off. (I know atoi and things like it exist, I just like knowing how things work). I've been tweaking this for some time now, and now it's a few hundred lines shorter, but still with the same error.

#include <stdio.h>

int main()
{
  char input[] = "123456789.123456", numcmp[] = "0123456789-";
  int i=0, i2=0, j, k, input_size = sizeof(input)-1, num[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, power;
  float output=0, add;

  int loop1=0, loop2=0;

  printf("input size = %d\n", input_size);

  while(i<input_size)
  {
    if(input[i] == '.')
    {
      k=i-1;
      j=i+1;

      while(k>=0)
      {
        printf("loop %d in k\n", loop1);
        power=i-k;
        i2=0;
        while(input[k] != numcmp[i2])
          i2++;
        printf("i2=%d\n", i2);
        add = num[i2];
        printf("add=%f\n", add);
        power--;
        printf("power=%d\n", power);
        while(power>0)
        {
          add=add*10;
          printf("add inside of k while loop = %f\n", add);
          power--;
        }
        output = output+add;
        printf("output = %f\n\n", output);
        k--;
        loop1++;
       }
      while(j<=input_size-1)
      {
        printf("loop %d in j\n", loop1);
        power=j-i;
        i2=0;
        while(input[j] != numcmp[i2])
          i2++;
        printf("i2=%d\n", i2);
        add = num[i2];
        add = add/10; 
        printf("add=%f\n", add);
        power--;
        printf("power=%d\n", power);
        while(power>0)
        {
          add=add/10;
          printf("add inside of j while loop = %f\n", add);
          power--;
        }
        output = output+add;
        printf("output = %f\n\n", output);
        k--;
        loop2++;
       }
      break;
      }
    i++;
    }
  printf("total output = %f\n", output);
  }

When I compile this code, I get:

input size = 16
loop 0 in k
i2=9
add=9.000000
power=0
output = 9.000000

loop 1 in k
i2=8
add=8.000000
power=1
add inside of k while loop = 80.000000
output = 89.000000

loop 2 in k
i2=7
add=7.000000
power=2
add inside of k while loop = 70.000000
add inside of k while loop = 700.000000
output = 789.000000

loop 3 in k
i2=6
add=6.000000
power=3
add inside of k while loop = 60.000000
add inside of k while loop = 600.000000
add inside of k while loop = 6000.000000
output = 6789.000000

loop 4 in k
i2=5
add=5.000000
power=4
add inside of k while loop = 50.000000
add inside of k while loop = 500.000000
add inside of k while loop = 5000.000000
add inside of k while loop = 50000.000000
output = 56789.000000

loop 5 in k
i2=4
add=4.000000
power=5
add inside of k while loop = 40.000000
add inside of k while loop = 400.000000
add inside of k while loop = 4000.000000
add inside of k while loop = 40000.000000
add inside of k while loop = 400000.000000
output = 456789.000000

loop 6 in k
i2=3
add=3.000000
power=6
add inside of k while loop = 30.000000
add inside of k while loop = 300.000000
add inside of k while loop = 3000.000000
add inside of k while loop = 30000.000000
add inside of k while loop = 300000.000000
add inside of k while loop = 3000000.000000
output = 3456789.000000

loop 7 in k
i2=2
add=2.000000
power=7
add inside of k while loop = 20.000000
add inside of k while loop = 200.000000
add inside of k while loop = 2000.000000
add inside of k while loop = 20000.000000
add inside of k while loop = 200000.000000
add inside of k while loop = 2000000.000000
add inside of k while loop = 20000000.000000
output = 23456788.000000

loop 8 in k
i2=1
add=1.000000
power=8
add inside of k while loop = 10.000000
add inside of k while loop = 100.000000
add inside of k while loop = 1000.000000
add inside of k while loop = 10000.000000
add inside of k while loop = 100000.000000
add inside of k while loop = 1000000.000000
add inside of k while loop = 10000000.000000
add inside of k while loop = 100000000.000000
output = 123456784.000000

loop 0 in j
i2 in j=1
add=0.100000
power in j=0
output in j = 123456784.000000

loop 1 in j
i2 in j=2
add=0.200000
power in j=1
add inside of while loop = 0.020000
output in j = 123456784.000000

loop 2 in j
i2 in j=3
add=0.300000
power in j=2
add inside of while loop = 0.030000
add inside of while loop = 0.003000
output in j = 123456784.000000

loop 3 in j
i2 in j=4
add=0.400000
power in j=3
add inside of while loop = 0.040000
add inside of while loop = 0.004000
add inside of while loop = 0.000400
output in j = 123456784.000000

loop 4 in j
i2 in j=5
add=0.500000
power in j=4
add inside of while loop = 0.050000
add inside of while loop = 0.005000
add inside of while loop = 0.000500
add inside of while loop = 0.000050
output in j = 123456784.000000

loop 5 in j
i2 in j=6
add=0.600000
power in j=5
add inside of while loop = 0.060000
add inside of while loop = 0.006000
add inside of while loop = 0.000600
add inside of while loop = 0.000060
add inside of while loop = 0.000006
output in j = 123456784.000000

total output = 123456784.000000

As you can see, it's somewhat working. The "add inside of while loop" shows the numbers are all good before being added together during "output = output + add" statements. And also, during loop 7, the integer part of the number changes from 123456789 to 123456788.

I'm baffled.

An answer to your question doesn't fit into a suitable stackoverflow answer since avoiding rounding errors when reading floating point numbers is quite difficult.

Here's a paper which describes the problems and gives a solution: How to read floating point numbers accurately , William D Clinger

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM