2016-02-27 38 views
3

我有一个程序,我目前使用byte[]布尔数组,即每个元素是01。我认为我应该尝试通过按位操作来加速程序。Java的非标准位操作

我需要解决的问题之一如下。例如,让

long a = 5 = "00101"(我不写在开头都提不起兴趣零)
long b = 24 = "10100"。 (我不写在开头都提不起兴趣零)

我需要动手术,O说,这样aOb在需要的位置,其中a1,需要的b的相应值和连接它们使得在此我们将会是

2 = "00010"。 (我不写在开头都提不起兴趣零)

a 00101 
O ↓ ↓ <- pick bits pointed by `1` in a 
b 10100 
    ↓ ↓ 
    1 0 -> concatenate selected bits -> 10 

编辑: 试图澄清: 好了,所以我们通过a无论是从左边或右边。如果我们遇到0,我们什么也没有。如果我们计算1,我们取相应指数b的值。例如,从左边下去,我们什么也不做了两个0 s,则我们发现1因此,我们采取相应的1b,我们找到另一个0a,什么也不做,然后我们在a找到另一个1,并采取相应的0b

编辑: 另一种方式把它是这样的:(?这是可能的)移位a的权利和读出值。如果是1,我们将b移到右侧,读取该值,将其存储到结果变量r并将r移到右侧。如果是0,我们将b转移到右侧,忘记价值,并与r无关。

编辑: 我会详细阐述一下目的,试图澄清我想要做什么。我们有一组布尔变量(比如5表示同意我们的例子)。变量b根据一些索引表示它们的状态数组。变量a中的1代表我们系统中对于某个布尔变量(比如0)有影响的布尔变量的索引,即我们的例子中的2和4。第二和第四布尔变量的值构成了与第0个变量相关联的真值表的一个可能输入。

有什么建议吗?编辑: 现在,我正在做的是这个。假设我们有一个带有5个布尔变量的系统,索引为$ 0,1,2,3,4 $。假设第0个变量是第2和第4个变量的函数,有一个事实表,即

2 | 4 |Output for 0 

0 | 0 | 0 
0 | 1 | 0 
1 | 0 | 0 
1 | 1 | 1 

我始终保持以这种方式排序表,所以我并不真正需要的左桌子的一部分。该表的右侧部分实现为byte[]阵列。为了找到输出,我只需将输入读取的整数表示作为二进制数字。例如。输入10是2,所以我的输出是我的byte[]阵列中索引2处的值。为了找到输入,我需要我的系统当前状态的一部分,它对应于所讨论的变量,即0。也就是说,我需要第二个和第四个变量的值,按顺序读取。

这样:

byte[] c = new byte[]{1,0,1,0,0}; //Corresponds to b above 
int[] ind = new int[]{2,4}; //Indices of c that we're interested in 
byte[] table = new byte[]{0,0,0,1}; //The truth table 
int j = 0; //Truth table index 
for(int i = 0; i < ind.length; i++) { 
    j += c[ind[i]]*(1 << (ind.length - 1 - i)) //Binary to integer 
} 
//Output is table[j] 
+2

定义“连接”。我不认为这个解释是严格的。我建议你制定一个真值表,以便我们看到你在说什么。到目前为止,它看起来与逻辑AND没有区别,但它也可能是逻辑蕴涵运算符。 – EJP

+1

你能澄清一点点吗?因为你所描述的只是一个&b,按位AND – Maljam

+0

你刚才定义的过程给出的结果是00100,而不是00010. – EJP

回答

3

顺便说一句, “10100” 是20不是24

class Main 
{ 
    public static void main (String[] args) throws java.lang.Exception 
    { 
     long a = 5; // "00101" 
     long b = 20; // "10100" 
     long c = 0; // the result 
     long pos = 1; // value of next position in result 

     while (a > 0) { 
      if ((a & 1) == 1) { 
       c = c + (pos * (b & 1)); 
       pos = pos << 1; 
      } 
      a = a >> 1; 
      b = b >> 1; 
     } 
     System.out.println("result=" + c); // 2 ("10") 
    } 
} 

你还结了一个循环,所以这真的只会节省内存。

+0

好的,所以它可能不会改进我的程序的执行时间。我仍然会尝试,但我现在必须离开。谢谢! –

+0

它实际上似乎有加速我的计划的潜力!原因主要是在我目前的实现中,我使用循环中的整数枚举了我的布尔系统的状态。对于每个整数,我必须将其转换为一个byte []数组,该数组给出整数的二进制表示形式。通过直接操作循环中的整数位,我可以避免转换步骤。 –

-2

你的描述是模糊的,但它是从默默无闻出现,这不是一个按位操作的。在这种情况下,我最初的建议是提供一个真值表,并且事实上这也是您应该如何实现的:通过查找表。

+0

逻辑与会导致00100.正确的算法应该导致00010. –

+0

我也不认为逻辑蕴涵是正确的,因为它会给出'11100'。 –

+0

我不明白如何用真值表来解决这个问题。 –

1

这些操作不太可能成为您程序的瓶颈。所以我的建议是使用一系列布尔运算符 - 不用担心一点一点的操作,它会让你的程序更难以理解和修改。

如果您真的担心在这些操作上花费的执行时间,请在尝试优化之前进行一些仔细的基准测试或分析。我的猜测是,将显示修改该代码没有任何收获。

+0

那么,性能可能是一个问题。我已经做了一些改进来加速它,但如果进一步加速可能,这将是非常好的。 –

2

这只是伪代码,所以不保证完整性和正确性。

r = 0 

for(int i=0; i<bits; i++) { 
    condition = (a >> i) & 1; 
    lookup = (b >> i) & 1; 
    if(condition == 1) { 
    r = (r << 1) | lookup; 
    } 
} 

鉴于这些输入...

a = 00101 
b = 10100 
bits = 5 

算法的行为如下。初始化结果。

r = 0 

取最后一位,位于i=0。为了做到这一点,转移到i的位置,并用这样的操作将其余的数字踢出:& 1。对ab这样做。然后检查过滤条件是否为真,在这种情况下,这意味着a的最后一位有1

i = 0 
condition = (00101 >> 0) & 1 = 00101 & 1 = 00001 = 1 
lookup = (10100 >> 0) & 1 = 10100 & 1 = 00000 = 0 
r   = (0 << 1) | 0 = 0 | 0 = 0 

i = 1 
condition = (00101 >> 1) & 1 = 00010 & 1 = 00000 = 0 
lookup = (10100 >> 1) & 1 = 01010 & 1 = 00000 = 0 
r   = 0 // no modification here 

i = 2 
condition = (00101 >> 2) & 1 = 00001 & 1 = 00001 = 1 
lookup = (10100 >> 2) & 1 = 00101 & 1 = 00001 = 1 
r   = (1 << 1) | 1 = 2 | 1 = 3 

的代码可以清理有两个功能,像这样:

lastAt(i, x) := (x >> i) & 1; 
concatTo(r, v) := (r << 1) | v; 

r = 0 
for(int i=0; i<bits; i++) { 
    if(lastAt(i, a) == 1) { 
    r = concatTo(r, lastAt(i, b)); 
    } 
} 
+0

谢谢!它似乎有可能在我的程序中缩短执行时间,但泰德的建议更快,所以我要接受他的回答:) –

+0

他的版本是正确的。我想这个答案帮助其他人知道你在找什么。 –

+0

是的,的确如此。 –