DuffDuff
DuffDuff

Reputation: 113

C program giving incorrect output for simple math!

(all are declared as ints, none are initialized to anything beforehand. I have included math.h and am compiling with -lm)

cachesize = atoi(argv[1]);
blocksize = atoi(argv[3]);
setnumber = (cachesize/blocksize);
printf("setnumber: %d\n", setnumber);
setbits = (log(setnumber))/(log(2));
printf("sbits: %d\n", setbits);

when given cachesize as 1024 and blocksize as 16 the output is as follows:

setnumber: 64
sbits: 5

but log(64)/log(2) = 6 !

It works correctly when given cachesize 512 and blocksize 32. I can't seem to win.

I'm really hoping that it's a stupid mistake on my part, and I'd be grateful if anyone could point out what it is! Thank you!

PS: I posted this in Yahoo Answers first but that was probably silly. Won't be doing that again.

Upvotes: 1

Views: 1044

Answers (2)

Stephen Canon
Stephen Canon

Reputation: 106127

What's happening is that neither log(2) or log(setnumber) are exactly representable as floating-point numbers, and their rounding errors are conspiring to cause their quotient to round down to something just smaller than 6, which then truncates to 5 when you convert to integer.

Using log2( ) will solve this problem on some platforms that have a good-quality math library, but the C standard does not actually guarantee anything about the accuracy of log( ) or log2( ) (indeed, some platforms just implement log2( ) as log( )/log(2), so it may give you the same problem you're having now).

You want to use the ilogb( ) function, which returns the exponent of its argument as a signed integer value.

setbits = ilogb(setnumber);

This has the added benefit of being quite a bit faster on some platforms.

(Admittedly, this use ilogb is not portable to systems that use non-radix-2 floating-point, but that's a much smaller concern then platforms that just have shoddy math libraries)

Upvotes: 1

Matthew Flaschen
Matthew Flaschen

Reputation: 284786

log returns a double. You should round instead of truncate. However, you can use log2 here.

Upvotes: 5

Related Questions