Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the nearest number, that is power of two, to another number?

Tags:

java

algorithm

I'm creating a world generator for my 2D game, which uses the Diamond-Square Algorithm in Java, and I've heard that it only works (or at least, only works well) with numbers that are 2n+1 (power of two).

The method that generates the world is called with generateWorld(width, height), but that creates a problem. I want to be able to input a width, and the function will find the nearest number which is a power of two, if the input width isn't. I don't really know how I can do this, so all help is greatly appreciated!

Summarizing: If one number isn't power of two, I want to find the nearest number to that one, which is a power of two.

like image 504
Daniel Kvist Avatar asked Dec 20 '14 18:12

Daniel Kvist


People also ask

How do you find the nearest number to the power of 2?

This works by finding the number you'd have raise 2 by to get x (take the log of the number, and divide by the log of the desired base, see wikipedia for more). Then round that up with ceil to get the nearest whole number power. This is a more general purpose (i.e. slower!)

How do you find the nearest number to a power?

If there are two nearest powers, consider the larger one. Explanation: The powers of 3 are 3, 9, 27, . . . Among these 3 is the nearest to 5 as it has a distance of 2. Explanation: The powers of 7 are 7, 49, 343, . . . 49 is the closest to 32 among these numbers. Explanation: Both 3 and 9 have distance = 3.

How do you find previous powers of 2?

Finding previous power of 2 If we somehow, can unset all bits except the left most bit in a binary representation of number we will get previous power of two of the given number. We will use Bitwise AND ( & ) operation to clear bits.

How do you find the nearest number to the power of 2 in Java?

Java. int lg = log(n, 2); // next power of two will have a bit set at position `lg+1`.


4 Answers

You can round up to a higher power of two (no change if it already was a power of two) like this:

x = x - 1;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;

It will give 0 for inputs where the next higher power of two does not exist.

The other candidate is simply half that. Then take the nearest.

like image 66
harold Avatar answered Nov 01 '22 11:11

harold


There are two candidates: 2^floor(log2(x)) and 2^ceil(log2(x)). Just check which of the two is closer.

For integers, you can use bit fiddling to find the most-significant set bit to get the exact value of floor(log2(x)). I've written about the idea before. Again this yields two candidates that you can check.

like image 36
Niklas B. Avatar answered Nov 01 '22 09:11

Niklas B.


Mathematically speaking, the closest power of 2 would be 2round(log2(x)). Java, unfortunately, doesn't have a pre-made method for log2, but luckily, it's easily doable with the pre-existing java.lang.Math functions:

int width = ...;
double log = Math.log(width) / Math.log(2);
long roundLog = Math.round(log);
long powerOfTwo = Math.pow(2, roundLog);
like image 22
Mureinik Avatar answered Nov 01 '22 11:11

Mureinik


Guava 20+

You have 3 useful methods:

  • IntMath.ceilingPowerOfTwo(x)
  • IntMath.floorPowerOfTwo(x)
  • IntMath.isPowerOfTwo(x)

and you can check which one of the floor power of 2 and the ceiling power of 2 is closer.

E.g.:

public static void main(String[] args) {
    for ( int i = 1 ; i < 13 ; i++ ) {
        nearestPowerOfTwo(i);
    }
}

private static void nearestPowerOfTwo(int x) {
    int ceil = IntMath.ceilingPowerOfTwo(x);
    int floor = IntMath.floorPowerOfTwo(x);
    System.out.print(x + " ---> ");
    if ( IntMath.isPowerOfTwo(x) ) {
        System.out.println(x + " (the number is power of 2)");
    } else if ( ceil - x > x - floor ) {
        System.out.println(floor);
    } else if (ceil - x == x - floor) {
        System.out.println(floor + " and " + ceil);
    } else {
        System.out.println(ceil);
    }
}

Output:

1 ---> 1 (the number is power of 2)
2 ---> 2 (the number is power of 2)
3 ---> 2 and 4
4 ---> 4 (the number is power of 2)
5 ---> 4
6 ---> 4 and 8
7 ---> 8
8 ---> 8 (the number is power of 2)
9 ---> 8
10 ---> 8
11 ---> 8
12 ---> 8 and 16

There are also LongMath and DoubleMath if the IntMath is not enough.

like image 34
ROMANIA_engineer Avatar answered Nov 01 '22 10:11

ROMANIA_engineer