如果我的数字大于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。这些是相机的典型图像尺寸。
答案 0 :(得分:5)
如果您的输入数字为x
,我认为您希望x/2^[(log x/14)/log 2]
,假设您希望目标号码位于[14,27]
区间内。
在java代码中,Math
的{{1}}函数会派上用场(尽管base-2对数会更好),你还需要一个整数强制转换(或者以某种方式找到最大的整数)小于log
)中的表达式。
这样做:让[]
成为您的输入,x
成为您想要找到的数字。然后,y
表示未知x=y*2^n
,而n
约为20(见上文)。显然,y
是n
的基数为2的对数。现在,如果您选择尽可能小的x/y
,将其称为y
,y'
的基数2对数的整数部分仍然是我们正在寻找的x/y'
,除非n
与x/y'
的差异大于2,否则假设重复除以2则不能。因此,我们有x/y
,因此n
。
答案 1 :(得分: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越接近20而不是13,但是14接近20而不是28。
答案 2 :(得分: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