6

如果我有一个大于 20 的数字,但它可以除以 2 而没有任何余数,我想确定哪个数字最接近 20。例如:

对于 2048 年,除以 2 足够的倍数将使我得到 16,这是我能得到的最接近 20。如果数字是 800,则最接近的是 25。

我可以编写一个循环,然后继续划分和比较范围并选择最接近的值。有没有更简单的方法,可能是通过移位?

编辑:当我说它除以 2 时,我的意思是它也一直除以 2。70 的数量只能平均分成 35。像 2048 或 1024 这样的数字将一直平分到 2。

样本编号:2048、1920、1600、1536、1080..640、352、320、176。这些是来自相机的典型图像尺寸。

4

3 回答 3

5

如果您输入的数字是x,我认为您想要x/2^[(log x/14)/log 2],假设您希望您的目标数字在区间内[14,27]

在 java 代码中,Mathlog函数会派上用场(尽管以 2 为底的对数会更好),并且您还需要整数转换(或者以某种方式找到小于 中的表达式的最大整数[])。

这是做什么的:让x成为您的输入并y成为您想要找到的数字。然后,x=y*2^n对于尚未未知n的,whiley大约是 20(见上文)。显然,n是 的以 2 为底的对数x/y。现在,如果你选择最小的y,调用它y',以 2 为底的对数的整数部分x/y'仍然是n我们正在寻找的,除非x/y'相差x/y超过 2 倍,假设重复除以 2 它不能。因此,我们有ny=x/2^n

于 2013-01-22T10:22:50.823 回答
2

您实际上想要修剪所有尾随零位,直到您有一个大于 13 的数字。

另一种方法是修剪所有零,如果结果太小,则将它们添加回来。

public static long func(long num) {
    if (num <= 26) return num;
    long trimZeros = num >>> Long.numberOfTrailingZeros(num);
    while(trimZeros <= 13) trimZeros <<= 1;
    return trimZeros;
}

26 比 13 更接近 20,但 14 比 28 更接近 20。

于 2013-01-22T10:38:53.347 回答
1

如果您想使用移位,可以从以下内容开始:

public static int func2(int val) {
    int min = Integer.MAX_VALUE;
    int close = 0;
    while (val > 1) {
        val = val >>> 1;
        if (Math.abs(val - 20) < min) {
            min = Math.abs(val - 20);
            close = val;
        }
    }
    return close;
}


public static void main() {
    for ( int i : new int []{2048, 1920, 1600, 1536, 1080, 640, 352, 320, 176}) {
       System.out.println( i + " -> " + func2( i ));
    }
}

印刷

2048 -> 16
1920 -> 15
1600 -> 25
1536 -> 24
1080 -> 16
640 -> 20
352 -> 22
320 -> 20
176 -> 22
于 2013-01-22T10:28:54.237 回答