julius caesar
julius caesar

Reputation: 23

Checking if a double is a power 2

I'm not sure how to check if a double is a power of 2. This is my code so far:

double x = Double.longBitsToDouble(
    Double.doubleToRawLongBits(n) & Double.doubleToRawLongBits(n - 1)
);

I used the following formula to find if the number is a power of 2:

n & (n - 1) == 0

But its not working.

Upvotes: 1

Views: 238

Answers (3)

Ames
Ames

Reputation: 101

This should work for all cases, though whether infinity is considered a power of 2 may be application specific.

public static boolean isPowerOfTwo(double val) {
    if (val <= 0.0 || Double.isNaN(val))
        return false; // You can't raise 2 to a power and get a negative number or zero.
    if (Double.isInfinite(val))
        return false; // Arguable assumption. val is bigger than MAX_VALUE but we don't really know if it's a power of 2 or not.
    long significand = Double.doubleToLongBits(val) & 0x000f_ffff_ffff_ffffL;
    if (val >= Double.MIN_NORMAL)
        return significand==0; // only the hidden 1 remains
    else
        return (Long.bitCount(significand) == 1); // denormalized, no hidden one, power of two only if exactly one bit in significand is set
}

Upvotes: 1

Dolda2000
Dolda2000

Reputation: 25855

If the problem is working with very large numbers, then Oleksandr's answer is better, but if you really want to check whether a double is an even power of two, you can just check if the mantissa is zero:

(Double.doubleToLongBits(n) & 0x000fffffffffffffL) == 0

To be more robust, you'll want to handle the edge cases for non-normalized numbers (infinities, NaNs, denormals, and perhaps decide on whether zeroes should return true), but those are normally edge cases.

Upvotes: 4

Oleksandr Pyrohov
Oleksandr Pyrohov

Reputation: 16266

To deal with big numbers you can use the BigInteger class:

public boolean isPowerOfTwo(BigInteger n) {
    if (n.compareTo(BigInteger.ZERO) <= 0) {
        return false;
    }
    return (n.and(n.subtract(BigInteger.ONE))).equals(BigInteger.ZERO);
}

Upvotes: 2

Related Questions