计算除以2的次数

时间:2010-12-20 09:33:21

标签: java language-agnostic math

问候。

我有一个我觉得很贵的java方法,我试图用数学表达式替换一些调用它。问题是,我吮吸数学。我的意思是真的很糟糕。

以下内容应该解释我试图利用的模式。

f(x)   -> y
f(x*2) -> f(x)+1

也就是说,每当我将x的值加倍时,y的值将比x / 2的值大1。 以下是一些示例输出:

f(5)   -> 6
f(10)  -> 7
f(20)  -> 8
f(40)  -> 9
f(80)  -> 10
f(160) -> 11
f(320) -> 12

我目前的做法是蛮力。我循环遍历X并测试在我达到5之前我可以将它减半的次数,最后我添加6.这样做并且比调用原始方法更快。但我一直在寻找更“优雅”或更便宜的解决方案。

接受的回答是那个设法帮助我而不指出我有多愚蠢的人:)

(标题可能很糟糕,因为我不知道我在找什么)

7 个答案:

答案 0 :(得分:6)

你是否认为你所看到的基本上是除以5,找到你有两个力量,并为这个力量加6?

“给定Y找出X的强大功能”的一般方法是使用对数。使用计算器尝试将日志64除以日志2,并看到你得到6。

所以 - 除以5,取日志,除以2的对数,然后加6。

答案 1 :(得分:3)

您正在寻找对数(基数2)

如果基数x为5,基数y为6,则log2(320/5)+ 6 = 12

在Java中,(Math.log(320 / x) / Math.log(2)) + y

其中xy是原始值(在此示例中为f(5) = 6

答案 2 :(得分:1)

你要找的是二进制表示中的位数,(对于基数10和10的对数)由log(x)/ log(2)

给出

答案 3 :(得分:1)

这不是答案,但我无法作出评论。考虑一个递归函数:

int someFunc(int n, int times) {
  if(n == 0) return 0;
  if( n % 2 == 0) return someFunc(n/2, times+1);
  else return n+times;
}

它能做你想做的吗?

someFunc(1, 0) -> 1
someFunc(2, 0) -> 2
someFunc(3, 0) -> 3
someFunc(5, 0) -> 5
someFunc(10, 0) -> 6
...

答案 4 :(得分:1)

首先,你的问题没有得到很好的解决。这是一个不应该问一个问题的例子(没有冒犯)。我将认为你的问题是:给定正整数x,找到整数m,n,使得x = m * 2 ^ n,其中m是奇数,然后返回y = f(x)= n + g(m)。因为你没有告诉如何计算奇数x的f(x),我假设给出g(。)。

如果在你的问题中,n不大,使用比简单循环(天真算法)更复杂的算法没有真正的好处。我将提出一个算法,它有利于n很大的情况(比如几百,几千)。我不懂Java,所以我以一般形式呈现算法(使用Python式语法)。

如果你采用x的二进制表示(b_ {N-1} ... b_1 b_0,b_i = 0或1)那么你的问题就会减少到从右边找到第一个比特1(即最低有效比特1) )。假设该位的位置是k(0 <= k <= N-1),则n = k并且m = x>&gt; ķ。我相信找到k的最佳方法是使用二进制搜索,这会产生O(log N)算法。算法如下(&lt;&lt;&gt;&gt;是移位运算符):

Algorithm: Input: x -> Outputs: (m, n)

if x is odd or x == 0: return (x, 0)  # x is odd when x & 1 == 1 or x % 2 == 1
N = ceil(log(x, 2))  # ceil: smallest integer larger than the argument
n = 0
orig_x = x

while x & 1 == 0:   # if bit 0 is 1 (i.e. x is odd), stop the search
  half = int(N/2)
  lowerhalf = x & ((1 << half) - 1)  # obtain the lower half
  if lowerhalf == 0:   # all zeros
    n += half
    x = x >> half
    N -= half
  else:
    x = lowerhalf
    N = half

return (orig_x >> n, n)

例如,如果N = 1000(x是1000位整数),则该算法最多需要10次迭代(而在最坏的情况下,朴素算法需要1000次迭代)。但是,实际执行时间取决于如何为1000位长度的整数实现位操作和==运算符。

答案 5 :(得分:0)

确定首先让我们注意到所有输入都是5的倍数,所以我们在输入中取出因子5;我们注意到输出从6开始,所以我们在输出中拉出6。我将这个新函数称为g

g(1)      0
g(2)      1
g(4)      2
g(8)      3
g(16)     4
g(32)     5
g(64)     6

现在这个函数希望更加熟悉 - g(x)x的力量来说简单2。为了做到这一点(用Java),我们可以使用java.lang.Math.pow(2, x)

剩下的就是从f获取g。但这很简单:

  • 给出f
  • 的输入
  • 除以5
  • 用作g
  • 的输入
  • 添加6

我会留给你的。

答案 6 :(得分:-1)

试试这个:

f(x) = log<sub>2</sub>(x/5) + 6