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 の対数の整数部分は、2倍以上の係数で異なる場合を除き、x/y'依然として探しているものです。できません。したがって、と したがってがあります。nx/y'x/yny=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 に答える