如何用J语言编写这个C表达式?

6

我该如何用J编写这个C表达式?(其中x是输入整数,a是临时变量)

((a= ~x & (~x >> 1)) ^= a ? 0 : (a ^ (a & (a - 1))) | (a ^ (a & (a - 1))) << 1);

.

编辑:

更易读的形式如下:

    int a = (~x) & ((~x) >> 1);
    if (a == 0) return 0;
    int b = a ^ (a & (a - 1));
    return b | (b << 1);

11
我们怎样才能找到最初写这个东西的混蛋? - GManNickG
这不是一份作业,而是一个挑战。解决完它后,我才意识到自己已经很久没有使用J语言了,也忘记了它的语法。想着这里可能有人会。 - Margus
3
这个表达式会导致未定义的行为。子表达式 ((a= ~x & (~x >> 1)) ^= a)a 进行了两次无序修改。 "更易读的形式" 不会导致未定义的行为,因此它不是同一件事情。 - James McNellis
3
@GMan一个真正的混蛋永远不会写if (a == 0) .. - ruslik
2个回答

5
没有测试的话,基本的转录会是这样的:
Shift =: (33 b.)
And   =: (17 b.)
Not   =: (26 b.)
Xor   =: (22 b.)
Or    =: (23 b.)

BastardFunction =: 3 : 0
  a =. (Not y) And (_1 Shift (Not y))
  if. a do.
    b =. a  Xor (a And a - 1)
    (1 Shift b) Or b
  else.
    0
  end.
)

但是可能有更聪明的方法。

嗯,我很少遇到0...也就是说,从未遇到过。 - MPelletier
验证值为0-9。我得到了与简化形式相同的结果。 - MPelletier
(2^31)-3,(2^31)-2和(2^31)-1都将返回0。 - MPelletier
经过验证,对于0到99的值,在C和J中结果相同。 - MPelletier

3

以下是一个小的分析(以“可读形式”的版本为例):

usnigned int nx = ~x;   // I suppose it's unsigned 
int a = nx & (nx >> 1); 
// a will be 0 if there are no 2 consecutive "1" bits.
// or it will contain "1" in position N1 if nx had "1" in positions N1 and N1 + 1
if (a == 0) return 0;   // we don't have set bits for the following algorithm
int b = a ^ (a & (a - 1));  
// a - 1 : will reset the least 1 bit and will set all zero bits (say, NZ) that were on smaller positions
// a & (a - 1) : will leave zeroes in all (NZ + 1) LSB bits (because they're only bits that has changed
// a ^ (a & (a - 1)) : will cancel the high part, leaving only the smallest bit that was set in a
// so, for a = 0b0100100 we'll obtain a power of two: b = 0000100
return b | (b << 1);    
// knowing that b is a power of 2, the result is b + b*2 => b*3

似乎算法在变量x中寻找从最低有效位开始的前2个连续的0位。 如果没有找到,则结果为0。 如果找到了,假设在位置PZ上,则结果将包含两个设置位:PZ和PZ+1。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接