-2

my program reads data from that file :

6 150

0 1.75

30 0.8

60 0.5

70 1

120 0.1

140 0.9

and inserts those numbers(It starts from the second row) into an array of structs and then calculates the 'time'. The results are fine but one; the third one('time') is 100 but the output is 99.999992.

Here is the program :

#include <stdio.h>
#include <stdlib.h>
int di,i,k,m;
float vi,time;
int n; 
int l;  

struct node 
{
    int distance;
    float velocity;

}DV[500000];

struct timeslist_node
{
    struct timeslist_node *left;
    int winner;
    int loser;
    double time;
    struct timelist_node *right;
};



double calctime(int d,float v);
void print_array();
main() 
{
    FILE *fp;


    fp=fopen("candidates.txt","r");
    if (fp==NULL) exit(2);
    fscanf(fp,"%d %d",&n,&l);
    printf("%d,%d\n",n,l);
    for(i=0;i<n;i++)
    {
        fscanf(fp,"%d %f",&DV[i].distance,&DV[i].velocity);
    }
    calctime(DV[i].distance,DV[i].velocity);
    print_array();
    fclose(fp);                   


    system("pause");
}

double calctime(int d,float v)
{      
    for(i=0;i<n;i++)
    {
        if (i == 0) 
        {
            {
                if (DV[n-1].velocity==DV[i].velocity)
                    time=-1;
            }

            time=((l-DV[n-1].distance)/(DV[n-1].velocity-DV[i].velocity));
            m=1;
            k=n;

        }
        else
        {

            {   if (DV[i-1].velocity==DV[i].velocity)
                time=-1;
            }
            time=((DV[i].distance-DV[i-1].distance)/(DV[i-1].velocity-DV[i].velocity));
            k=i;
            m=i+1;
        }
        printf ("t %d %d=%lf\n",m,k,time);
    }
}
void print_array()
{
    for(i=0;i<n;i++)
        printf("D[%d],V[%d] = %d %.2f\n ",i,i,DV[i].distance,DV[i].velocity );
}
Deidrei
  • 2,125
  • 1
  • 14
  • 14
  • I'm pretty sure this just boils down to the fact that `float` has limited precision. – davmac Jun 10 '14 at 09:30
  • 1
    [What Every Computer Scientist Should Know About Floating-Point Arithmetic](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html), that's a more technical article about floating point numbers. – Dirk Jun 10 '14 at 09:31
  • The program should do : (60-30)/(0.8-0.5) How is that even close to the limits of float? – user3670503 Jun 10 '14 at 09:33
  • 2
    Well, for one, because [0.80 doesn't have perfect representation in IEEE 754 floating point](http://ideone.com/uA1fnC). Read the article linked by Dirk (yes, its a long stretch, but you'll remember it quite-literally the rest of your life). – WhozCraig Jun 10 '14 at 09:38
  • There is also a series of [blog posts by Eric Lippert](http://blogs.msdn.com/b/ericlippert/archive/2005/01/10/floating-point-arithmetic-part-one.aspx) which are less mathematical than the other article I linked. – Dirk Jun 10 '14 at 09:42
  • it's not because of the limit. It's because you can't represent most decimal fractional numbers in binary. There were already thousands duplicates about this on SO – phuclv Jun 10 '14 at 09:42
  • http://stackoverflow.com/search?q=c+0.1+float http://stackoverflow.com/questions/13542220/why-for-i-0-1-i-1-0-i-0-1-doesnt-break-at-i-1-0 http://stackoverflow.com/questions/5257166/java-floats-and-doubles-how-to-avoid-that-0-0-0-1-0-1-0-9000001?rq=1 – phuclv Jun 10 '14 at 10:18

3 Answers3

1

Thats happens because floating point numbers have a limited precision. If you want to know why, have a deeper look at how floating point are stored in the memory. http://en.m.wikipedia.org/wiki/Floating_point.

Malic Of Sdom
  • 431
  • 1
  • 3
  • 10
  • 1
    It's **not** because of the precision. Even if you have unlimited precision you still can't represent 0.8 in binary float correctly – phuclv Jun 10 '14 at 10:00
  • 2
    @luu vinh phuc if you *had* unlimited precision, wou could represent every real number correctly. Unfortunalty, unlimited precision needs infinite size – Ingo Leonhardt Jun 10 '14 at 10:10
0

Typical float will handle math as expected, but only to within a certain range and precision.

That precision is typically about 6, maybe 7, significant digits. See FLT_DIG in <float.h>. 99.999992 is the results of printing a number to 8 significant digits. Using printf("%.5e", some_float) will limit the output to its realistic precision.

Using double rather than float will typically provide additional range and precision. But the same issues occur, albeit with more extreme numbers.


As many other have said, there are many issues contributing to the the fact that the sum was printed as 99.999992 rather than 100.0.

First, the sum is most likely precisely 99.99999237060546875, which is the previous float, assuming binary32, to 100.0. Printing a number like 99.99999237060546875 to 8 significant places is moving beyond reasonable precision expectations of float in C. "%f" prints a number with 6 digits following the decimal point. Since the number was 99.99999237060546875, a rounded number of 99.999992 with 2 + 6 significant digits was printed.

2nd: various math operations have inexact results. This is expected with 1.0/3.0, but it also happens with 100 + 0.1. This idea is outlined in the classic reference What Every Computer Scientist Should Know About Floating-Point Arithmetic

3rd, recall floating point numbers are not linearly, but logarithmically distributed. There are about as many numbers between 1.0 and 10.0 as between 10.0 and 100.0.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • Thanks a lot man! You were very helpful. Please if you have time and you want, check my other question about trees http://stackoverflow.com/questions/24140517/apparently-nothing-is-inserted-into-the-tree – user3670503 Jun 10 '14 at 12:41
-2

Can't you use Round for this?

Round(*STRING*);

Source: http://msdn.microsoft.com/en-us/library/75ks3aby(v=vs.110).aspx

jjeroennl
  • 1
  • 2