Java 如何找到与另一个数最接近的数,即二的幂?
我正在为我的2D游戏创建一个世界生成器,它使用Java中的钻石方块算法,我听说它只对2n+1(二的幂)的数字有效(或者至少有效) 生成世界的方法使用Java 如何找到与另一个数最接近的数,即二的幂?,java,algorithm,Java,Algorithm,我正在为我的2D游戏创建一个世界生成器,它使用Java中的钻石方块算法,我听说它只对2n+1(二的幂)的数字有效(或者至少有效) 生成世界的方法使用generateWorld(width,height)调用,但这会产生问题。我希望能够输入一个宽度,如果输入宽度不是,函数将找到最接近的数字为二的幂。我真的不知道如何才能做到这一点,所以非常感谢所有的帮助 总结:如果一个数字不是二的幂,我想找到与之最接近的数字,它是二的幂。有两个候选者:2^floor(log2(x))和2^ceil(log2(x))
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请将此答案解释为数学伪码,而不是javaceil(log(x))
四舍五入?@TheDestroyer 12是的。我如何检查一个数字是否是二的幂?很好,我忽略了一个事实,我们实际上不需要知道日志,只需要知道电源:)干净和简单实际上,我认为这是最简单的一个。此外,它还易于与int
s一起使用。谢谢它是如何工作的?我不能得到你在这里做的。@ VikasgppTa在中间的移位/链复制最高设置位到它下面的所有位。因此,向其添加一个将导致比输入高出下一个二次方。为了向上取整而不是一直向上取整,一开始就减去一。