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:
D:... copy-pasted 100s of times through our codebase.
-
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.
-
@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'?
-
@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
FTFYsmellstench.
-
@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.)