More fun with floating points



  • By coincidence this is on a similar topic to today's CodeSOD. I present to you this rounding algorithm copy-pasted 100s of times through our codebase.

        roundIt = 1;
        sprintf_s(rndx, "%50.12f", givenDoubleValue);

        if (rndx[strlen(rndx) - 12] == '0')
          if (rndx[strlen(rndx) - 11] == '0')
            roundIt = 0;

        if (roundIt)
        {
          rndx[strlen(rndx) - 12] = '0';
          rndx[strlen(rndx) - 11] = '0';
        }

        memset (x, '\0', sizeof x);

        strncpy_s(x, rndx, (strlen(rndx) - 10));

        givenDoubleValue = atof(x);
        if (roundIt)
          givenDoubleValue += 1.00;



  • By about the 3rd line of this code, I'd be thinking -- there must be a better way of doing this. Converting a numeric value into a string for further processing is almost always a code smell.



  • @Mithious said:

    ... copy-pasted 100s of times through our codebase.

    D:



  • So 1.01 rounds to 2?  It is similar to truncating to two decimal places and then running through ceil().

    Fun things happen to negative numbers.  -0.99 rounds to 1!

    And hopefully you never have large numbers (like 1e50) or it will abort your program.



  • Discourse touched me in a no-no place

    @jnz said:

    And hopefully you never have large numbers (like 1e50) or it will abort your program.
    %f would (should) never return exponential formatted numbers - you need %g for that:

    [pjh@pjh tmp]$ cat ./format.c
    #include <stdio.h>
    int main(void){
            double d =1e100;
            printf("%.12f\n", d);
            printf("%.12g\n", d);
            return 0;
    }
    [pjh@pjh tmp]$ make format
    cc     format.c   -o format
    [pjh@pjh tmp]$ ./format
    10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104.000000000000
    1e+100
    [pjh@pjh tmp]$


  • @jnz said:

    Fun things happen to negative numbers.  -0.99 rounds to 1!

    I was wondering if anyone would notice that one. :)

     



  • I thought you were supposed to always round down and then deposit the extra into your own bank account - after beating the crap out of your copier, of course.

    Or am I 'jumping to conclusions'?


  • BINNED

    @DrPepper said:

    By about the 3rd line of this code, I'd be thinking -- there must be a better way of doing this. Converting a numeric value into a string for further processing is almost always a code smell stench.
    FTFY


  • Discourse touched me in a no-no place

    @jnz said:

    So 1.01 rounds to 2?  It is similar to truncating to two decimal places and then running through ceil().

    Actually, it's just like running through ceil(). And then adding 1 if the original number was negative, just for giggles.
    @jnz said:
    And hopefully you never have large numbers (like 1e50) or it will abort your program.

    You can't tell that for sure; it depends on the buffer sizes and we were never told them. (Most likely true though.)


Log in to reply