tags:

views:

142

answers:

2

(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.

+5  A: 

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

Matthew Flaschen
Excellent! Thank you. =]
DuffDuff
In addition, there is a `log2()` function to directly get base 2 logarithms, instead of doing that division yourself.
Carl Norum
You posted that a second before I added that, Carl. :)
Matthew Flaschen
I read that log2 requires "-std=c99" and I'm lazy with my makefiles. If I have another question in the same program but unrelated to this problem should I post it here or make a whole new question?
DuffDuff
@DuffDuff: Questions on unrelated issues should be posted separately. That said, the answer is probably `CFLAGS += -std=c99`
Novelocrat
Hahaha, that is NOT what I was going to ask, but thank you. =D
DuffDuff
A: 

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)

Stephen Canon