#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    6
    Rep Power
    0

    C types problem :(


    1.4000*10=14 but it gives 13

    int sum=0;
    float float_sum=0.0;
    float_sum=1.4000;
    sum=float_sum*10;
    printf(" Sum : %d\n\n",sum);

    I can't understand why? Please help me guys :(
  2. #2
  3. Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Sep 2013
    Location
    Saint-Petersburg, Russia
    Posts
    236
    Rep Power
    28
    Obviously 1.4 could not be represented exactly as a binary fraction value, so it becomes 1.399999.... (print it full to see)

    When you multiply by 10 you get 13.99999 - and then casting to int simply cuts fraction, so you are left with your 13.

    Use "round" function to round results before casting to int, for example.

    This exercise could be of help too:
    Rounding at CodeAbbey
  4. #3
  5. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,171
    Rep Power
    2222
    Also print out sum in floating-point format. You should find that it's something like 13.99999. When you convert a float to an integer, you truncate it, which means that you chop off the fractional part and keep the integer part. So 13.99999 truncates to 13.

    BTW, sum could just as easily have been 14.000001, which would have truncated to 14. Read up on IEEE 754, which is the floating-point format being used. It's a form of "scientific notation", in which you have a fraction called the mantissa and an exponent that you use to move the binary point, just as you do in decimal. Yes, I did say "binary point", because that mantissa is in binary (base 2) instead of decimal (base 10) and you multiply it by two raised to the exponent. You can express exactly a value which is a power of two (eg, 1, 2, 4, 8, 16, 32, 64, etc), but all other numbers you can only approximate. You can get very very close to that value, but not exactly. It is therefore a logic error to expect a floating-point operation to yield an exact value.

    When you investigate the floating-point format, these utilities I wrote may help you to see what various values look like. They both depend on being run on a little-endian machine, such as an Intel.

    f2hex.c: converts a float value to hex
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
        int i;
        float f;
        
        if (argc != 2)
        {
            fprintf(stderr,"Usage: f2hex <floating-point value>");
            exit(1);
        }
        
        f = (float)atof(argv[1]);
        printf("%g = ",f);
        
        for (i=3; i>= 0; i--)
            printf(" %02X",((unsigned char*)(&f))[i]);
        printf("\n"); 
        
        return 0;       
    }
    d2hex.c: converts a double value to hex
    Code:
    #include <stdlib.h>
    #include <stdio.h>
    
    int main(int argc, char *argv[])
    {
        int i;
        double f;
        
        if (argc != 2)
        {
            fprintf(stderr,"Usage: d2hex <doubleing-point value>");
            exit(1);
        }
        
        f = atof(argv[1]);
        printf("%g = ",f);
        
        for (i=7; i>= 0; i--)
            printf(" %02X",((unsigned char*)(&f))[i]);
        printf("\n"); 
        
        return 0;       
    }
  6. #4
  7. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    1
    Rep Power
    0
    Originally Posted by bashburak
    1.4000*10=14 but it gives 13

    int sum=0;
    float float_sum=0.0;
    float_sum=1.4000;
    sum=float_sum*10;
    printf(" Sum : %d\n\n",sum);

    I can't understand why? Please help me guys :(
    The problem is that sum is of type integer and you are trying to stuff a float into it. The float, float_sum, gets a part of it indiscriminately chopped off to fit into sum, which is smaller than a float, and causes a loss of data and hence the error.

    Change sum to type float and that will fix it. Didn't your compiler issue a warning of possible loss of data for this line: sum=float_sum*10;?

    And in case you didn't know, literals like 1.4000 or 10 also have a type. Any number that doesn't have a decimal point is an integer. And any number that has a decimal point is automatically a double, unless a "f" is used to denote a float type.

    For example:
    10 = integer.
    1.40 = double.
    1.40f = float.

    In the line above, float_sum=1.4000;, you should be getting some kind of warning, like "truncation from 'double' to 'float' ". The compiler will give you a warning when it starts chopping things up so that you can check to see if there is any loss of data involved. It is good practice to compile so that there are no warnings in the first place.

    Change this line: float_sum=1.4000; to this: float: sum=1.4000f; to eliminate the compiler's warning.
  8. #5
  9. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    6
    Rep Power
    0

    I got it now :)


    MandrewP, i am using similar code in a function which should return int type, so changing int sum to float is not solving my problem. thanks anyway for consideration :)

    rodiongork, ı followed what u said and printed to see variations.
    you are right, 14.0 is something like 13.999....

    so here it is with examples :


    code :
    -----------------------------------------------------------

    /*first of all if we assign to a int variable something like f_x*10 that which has reel value result, it looses data. */

    int i_x;
    float f_x;
    f_x=1.4;
    i_x=f_x*10; prints
    printf("\n\nfloat x : %.17f \n",f_x); // 13.9999997615......
    printf("\n\n int x : %d \n",i_x); // prints 13


    /*if we assign to a reel variable f_a*10 = 13.9999997615......
    new f_a will be 14.000000... */

    int i_a;
    float f_a;
    f_a=1.4*10;
    printf("\n\nfloat a : %.17f \n",f_a); //prints 14.00000...
    i_a=f_a;
    printf("\n\n int a : %d \n",i_a); // prints 14


    //similar here

    int i_b;
    float f_b;
    f_b=1.4;
    f_b=f_b*10;
    printf("\n\nfloat b : %.17f \n",f_b);
    i_b=f_b;
    printf("\n\n int b : %d \n",i_b);

    -----------------------------------------------------------

    after all, i understood that, when we wont to assign reel value(like 14.0) to a int variable, first we will assign it to a reel
    variable and then we will assign reel variable to a int variable.
    assigning "reel result" directly to a int variable may cause data loses.

    am I right ? :)

    sorry for weak English :p
  10. #6
  11. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,111
    Rep Power
    1803
    Originally Posted by bashburak
    MandrewP, i am using similar code in a function which should return int type, so changing int sum to float is not solving my problem.
    To force a conversion to integer to round to the nearest integer, add 0.5 to the floating-point value prior to the integer cast:
    Code:
    float float_sum = 1.4f ;
    int sum = (int)((float_sum * 10.0f) + 0.5f) ;
    printf( "Sum : %d\n", sum ) ;
    Try that with float_sum = 1.34, 1.35, 1.39, 1.44, and 1.45 for example to see how it works.
    Last edited by clifford; October 8th, 2013 at 03:01 PM.
  12. #7
  13. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,111
    Rep Power
    1803
    Originally Posted by bashburak
    printf("\n\nfloat x : %.17f \n",f_x); // 13.9999997615......
    The single precision "float" type is only good for 6 decimal significant figures, so a precision of .17 is rather too much. "double" is only good for 15 even.
  14. #8
  15. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    6
    Rep Power
    0
    To force a conversion to integer to round to the nearest integer, add 0.5 to the floating-point value prior to the integer cast:
    I also used your method clifford in :

    int sum_of_digit_values2(int);
    int sum_of_digit_values3(int);

    functions, it works, thanks :)

    Code:
    int sum_of_digit_values1(int);
    int sum_of_digit_values2(int);
    int sum_of_digit_values3(int);
    
    int main()
    {
        int number;
        printf("\n Enter a number : ");
        scanf("%d",&number);
        printf("\n\n 1.Sum of values of digits : %d\n\n",sum_of_digit_values1(number));
        printf("\n\n 2.Sum of values of digits : %d\n\n",sum_of_digit_values2(number));
        printf("\n\n 3.Sum of values of digits : %d\n\n",sum_of_digit_values3(number));
    }
    int sum_of_digit_values1(int x)
    {
       int decimal,sum=0;
       do
       {
           decimal = (int)(10.0f*((float)(x/10.0f)-x/10)+0.5f);
           printf("\n\tDecimal part : %d \n",decimal);
           x=x/10;
           sum+=decimal;
       }
       while(x>=1);
            return(sum);
    }
    int sum_of_digit_values2(int x)
    {
       int sum=0;
       do
       {
           sum+=x%10;
           x=x/10;
       }
       while(x>0);
            return(sum);
    }
    
    int sum_of_digit_values3(int x)
    {
       int sum=0;
       do
       {
           sum+=(int)(10.0f*((float)(x/10.0f)-x/10)+0.5f);
           x=x/10;
       }
       while(x>=1);
            return(sum);
    }
  16. #9
  17. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,111
    Rep Power
    1803
    Note that in teh following expression (ant other similar constructs in your code):
    Originally Posted by bashburak
    Code:
           decimal = (int)(10.0f*((float)(x/10.0f)-x/10)+0.5f);
    the sub-expression x/10.0f already has type float because the 10.0f forces an implicit cast before your explicit cast. If you want to avoid the implicit cast then the expression should be:
    Code:
           decimal = (int)(10.0f * (((float)x / 10.0f) - x / 10) + 0.5f) ;
    in either cast you get the same result and it may even be clearer to remove the explicit cast since teh intent is clear by the use of 10.0f:
    Code:
           decimal = (int)(10.0f * ((x / 10.0f) - x / 10) + 0.5f) ;
  18. #10
  19. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Oct 2013
    Posts
    6
    Rep Power
    0
    function pow() has real type, so if i assign it to a int variable, will it cause data lose?

    example :

    int delta;
    delta=pow(b,2)-4*a*c;

    or should i convert it to int like written below?

    int delta;
    delta=(int)pow(b,2)-4*a*c;
  20. #11
  21. Contributing User

    Join Date
    Aug 2003
    Location
    UK
    Posts
    5,111
    Rep Power
    1803
    Originally Posted by bashburak
    or should i convert it to int like written below?
    In terms of the result, there is no difference between an implicit or an explicit cast, an explicit cast however is a clear indication that you intended to assign an integer and that it is not a programming error. This will help anyone who later maintains your code (including yourself). It may also silence compiler or static analysis warnings.

IMN logo majestic logo threadwatch logo seochat tools logo