tags:

views:

57

answers:

1

I'm trying to round a number to the next smallest power of another number. The number I'm trying to round is always positive. I'm not particular on which direction it rounds, but I prefer downwards if possible.

I would like to be able to round towards arbitrary bases, but the ones I'm most concerned with at the moment is base 2 and fractional powers of 2 like 2^(1/2), 2^(1/4), and so forth. Here's my current algorithm for base 2. The log2 I multiply by is actually the inverse of log2:

double roundBaseTwo(double x)
{
    return 1.0 / (1 << (int)((log(x) * log2))
}

Any help would be appreciated!

Edit: If it helps, the specified range of my input is always a non-zero, positive floating point number. It's almost always within the range of (0, 1], very rarely larger than 1.

+3  A: 

You've got the right idea; for any base x, x ^ floor( log_x(n) ) is what you want. (Where log_x represents 'log to the base x')
In C#:

static double roundBaseX(double num, double x)
{
    return Math.Pow(x, Math.Floor(Math.Log(num, x)));
}

If you can't take logarithms to an arbitrary base, just use the formula: log_x(n) = log(n) / log(x)

tzaman
Thanks! That's just what I was looking for. Would you happen to know if there's any faster way of doing it, or am I stuck doing it this way? I was thinking of potentially doing a lookup table for common values, since this was something that would be computed extremely frequently in my main loop.
Sagekilla
You're welcome. :) About speeding it up, a lookup table would do rather well, I think. If you can store all the powers of your base in an array (i.e. enough to cover the entire range you need), a simple binary search would be all you needed to do your rounding. Of course, you'd need one such array for every base you use.
tzaman