Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/376.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何找到与另一个数最接近的数,即二的幂?_Java_Algorithm - Fatal编程技术网

Java 如何找到与另一个数最接近的数,即二的幂?

Java 如何找到与另一个数最接近的数,即二的幂?,java,algorithm,Java,Algorithm,我正在为我的2D游戏创建一个世界生成器,它使用Java中的钻石方块算法,我听说它只对2n+1(二的幂)的数字有效(或者至少有效) 生成世界的方法使用generateWorld(width,height)调用,但这会产生问题。我希望能够输入一个宽度,如果输入宽度不是,函数将找到最接近的数字为二的幂。我真的不知道如何才能做到这一点,所以非常感谢所有的帮助 总结:如果一个数字不是二的幂,我想找到与之最接近的数字,它是二的幂。有两个候选者:2^floor(log2(x))和2^ceil(log2(x))

我正在为我的2D游戏创建一个世界生成器,它使用Java中的钻石方块算法,我听说它只对2n+1(二的幂)的数字有效(或者至少有效)

生成世界的方法使用
generateWorld(width,height)
调用,但这会产生问题。我希望能够输入一个
宽度
,如果输入宽度不是,函数将找到最接近的数字为二的幂。我真的不知道如何才能做到这一点,所以非常感谢所有的帮助


总结:如果一个数字不是二的幂,我想找到与之最接近的数字,它是二的幂。

有两个候选者:
2^floor(log2(x))
2^ceil(log2(x))
。只需检查两者中哪一个更接近


对于整数,您可以获取
floor(log2(x))的精确值
。我有。同样,这会产生两个候选项,您可以进行检查。

从数学上讲,2的最接近幂为2round(log2(x))。不幸的是,Java没有为log2预先制作的方法,但幸运的是,通过预先存在的
Java.lang.Math
函数,它很容易实现:

int width = ...;
double log = Math.log(width) / Math.log(2);
long roundLog = Math.round(log);
long powerOfTwo = Math.pow(2, roundLog);

您可以将其四舍五入为更高的二次幂(如果它已经是二次幂,则没有变化),如下所示:

x = x - 1;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return x + 1;
如果不存在下一个更高的二次幂,则输入将为0

另一位候选人只是这个数字的一半。然后坐最近的。

番石榴20+ 您有3种有用的方法:

  • IntMath.ceilingPowerOfTwo(x)
  • IntMath.floorPowerOfTwo(x)
  • IntMath.isPowerOfTwo(x)
你可以检查2的地板功率和2的天花板功率哪一个更接近

例如:

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);
    }
}
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

如果
IntMath
不够,还有
LongMath
DoubleMath

您确定不想将其四舍五入为二的幂吗?选择最近的一个可以使你的世界比你要求的更小。一个大的总是可以在最后被削减。是的,现在当你这么说的时候,这听起来是一个更好的方式。我会试着用答案把它归纳起来。谢谢
^
是java中的按位异或运算符,而不是您可能期望的幂运算。@kinbiko请将此答案解释为数学伪码,而不是java
ceil(log(x))
四舍五入?@TheDestroyer 12是的。我如何检查一个数字是否是二的幂?很好,我忽略了一个事实,我们实际上不需要知道日志,只需要知道电源:)干净和简单实际上,我认为这是最简单的一个。此外,它还易于与
int
s一起使用。谢谢它是如何工作的?我不能得到你在这里做的。@ VikasgppTa在中间的移位/链复制最高设置位到它下面的所有位。因此,向其添加一个将导致比输入高出下一个二次方。为了向上取整而不是一直向上取整,一开始就减去一。