Thread: Correct my code as it is giving approximate float value but not exact

  1. #1
    Registered User
    Join Date
    Jul 2011
    Location
    India
    Posts
    20

    Correct my code as it is giving approximate float value but not exact

    Code:
    //code to convert string(containing digits) to equivalent float value
    //Its giving approx value but not exact value
    #include<stdio.h>
    #include<ctype.h>
    #include<math.h>
    int main()
    {
        char a[20];
        int c,i=0,k,sign=1;
        float f=0;
        while((c=getchar())!='\n' && i<19)
        {
            a[i]=c;
            i++;
        }
        a[i]='\0';
        for(i=0;a[i]==' ' && i<19;i++)
        ;
        if( (a[i]=='+' && (sign=1)) || (a[i]=='-' && (sign=-1)) )
            i++;
        for(;a[i]!='\0'&&a[i]!='.';i++)
        {
            f=f*10+(a[i]-'0');
        }
        if(a[i]=='.')
            for(k=-1,i++;a[i]!='\0';i++,k--)
                f=f+pow(10,k)*(a[i]-'0');
        f*=sign;
        printf("\n num is %f",f);
        return 0;
    }
    o/p:
    123.654
    
     num is 123.653999

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    That's working as designed.

  3. #3
    Registered User
    Join Date
    Jul 2011
    Location
    India
    Posts
    20
    I got output as shown above. I did on gcc compiler....

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    And that is the correct output.

    See here: IEEE-754 Reference Material

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Do you think the 32bits representing a float should be able to give you more digits than the 32 bits representing an integer? Wouldn't that make integers completely pointless? If you want accuracy, use integers. If you want estimations of floating point numbers, use floats or doubles.


    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by ackr1201 View Post
    Code:
    //code to convert string(containing digits) to equivalent float value
    //Its giving approx value but not exact value
    #include<stdio.h>
    #include<ctype.h>
    #include<math.h>
    int main()
    {
        char a[20];
        int c,i=0,k,sign=1;
        float f=0;
        while((c=getchar())!='\n' && i<19)
        {
            a[i]=c;
            i++;
        }
        a[i]='\0';
        for(i=0;a[i]==' ' && i<19;i++)
        ;
        if( (a[i]=='+' && (sign=1)) || (a[i]=='-' && (sign=-1)) )
            i++;
        for(;a[i]!='\0'&&a[i]!='.';i++)
        {
            f=f*10+(a[i]-'0');
        }
        if(a[i]=='.')
            for(k=-1,i++;a[i]!='\0';i++,k--)
                f=f+pow(10,k)*(a[i]-'0');
        f*=sign;
        printf("\n num is %f",f);
        return 0;
    }
    o/p:
    123.654
    
     num is 123.653999
    Congratulations.... your program works.

    And yes... computers do indeed make mistakes.
    Floating point math on computers is always an approximation limited by the bit depth of the calculation...

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    In base 10, 2/3 is 0.666666.... It never ends, and you can never represent 2/3 perfectly with only a finite number of digits. Furthermore, when you give a truncated value (say, only 5 decimal places), you typically round to 0.66667. It's inexact, but close enough for most things.


    Computers use base 2, but just like base 10, some fractions can't be represented perfectly. Also, they are limited to the number of bits they can use for floating point representation, so they get as close as they can, but it might not be perfect. In base 10, 123.654 is an exact representation of the quantity 123654 / 1000, but 123654 / 1000 doesn't have an exact representation in base 2, hence the approximation.


    If you asked for only 3 places after the decimal (what you're currently asking for is the default, 6), the computer would round to 123.654. Try putting printf("\n num is %.3f", f); and see what happens.


    The following article may be a little complicated, but it's a very thorough explanation of how computers handle floats, the shortcomings and how to deal with it.


    What Every Computer Scientist Should Know About Floating-Point Arithmetic

  8. #8
    Registered User
    Join Date
    Jul 2011
    Location
    India
    Posts
    20

    See the following code it is giving exact answer compared to my answer

    Code:
    //concept took from K&R book
    void main()
    {
    char s[]="123.654";
    double val, power;
    int i=0, sign,c;
    for (i = 0; isspace(s[i]); i++) //skip white space
    ;
    sign = (s[i] == '-') ? -1 : 1;
    if (s[i] == '+' || s[i] == '-')
    i++;
    for (val = 0.0; isdigit(s[i]); i++)
    val = 10.0 * val + (s[i] - '0');
    if (s[i] == '.')
    i++;
    for (power = 1.0; isdigit(s[i]); i++) {
    val = 10.0 * val + (s[i] - '0');
    power *= 10;
    }
    printf("%f",sign*(val/power));
    }
    O/P:
    123.654000

  9. #9
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    So obviously you can get closer to the right number with a double precision than you can with a float (in fact, you get just about twice as many correct digits). That just moves the "wrong numbers" past the place where printf stops. Try printing with %.18f or something and you'll see the difference.

  10. #10
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    First problem with that code, it's int main(void) and return an int at the end. Read this FAQ article: Cprogramming.com FAQ > main() / void main() / int main() / int main(void) / int main(int argc, char *argv[])

    Second, your first bit of code uses float (32 bits of precision), while the second piece uses a double (64 bits of precision). Neither is "exact". If you print enough decimal places, you will see even the second bit of code stores an imprecise number, but rounds it correctly when only printing a few decimal places. Instead of one printf line with the default "%f", put the following at the end of each program:
    Code:
    printf("The value to 20 decimal places is %.20f", value);
    printf("The value to the default (6) decimal places is %f", value);
    printf("The rounded to 3 decimal places is %.3f", value);
    If you put that in both programs and try both programs, you will see that the number is only an approximation, but using more bits (i.e. double instead of float) gets you closer to exact, so you can print more decimal places before the error becomes apparent.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sprintf of float giving "1.#QO"
    By Mafepero in forum C++ Programming
    Replies: 2
    Last Post: 03-03-2008, 04:52 AM
  2. Giving instruction to an executing C code
    By darkwalk in forum C Programming
    Replies: 2
    Last Post: 10-24-2006, 12:01 PM
  3. What is the correct way to enter a float pointer?
    By Zalbik in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2003, 06:08 PM
  4. Replies: 3
    Last Post: 07-24-2002, 08:46 AM