简体   繁体   English

Java的非标准位操作

[英]Nonstandard bit operations for Java

I have a program where I am currently using byte[] boolean arrays, ie each element is either 0 or 1 . 我有一个程序,我目前使用byte[]布尔数组,即每个元素是01 I thought I should try to speed up the program by using bitwise operations. 我想我应该尝试使用按位运算来加速程序。

One of the problems that I would need to solve goes as follows. 我需要解决的问题之一如下。 For example , let 例如,让我们

long a = 5 = "00101" (I don't write all uninteresting zeros at the beginning) long a = 5 = "00101" (我不会在开头写下所有无趣的零)
long b = 24 = "10100" . long b = 24 = "10100" (I don't write all uninteresting zeros at the beginning) (我不会在开头写下所有无趣的零)

I need an operation, O say, such that aOb takes at the positions where a is 1 , takes the corresponding values of b and concatenates them so that in this case we would be 我需要动手术, O说,这样aOb需要的位置,其中a1 ,采取的相应值b和连接它们,以便在这种情况下,我们会

2 = "00010" . 2 = "00010" (I don't write all uninteresting zeros at the beginning) (我不会在开头写下所有无趣的零)

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

EDIT: Attempt to clarify: Alright, so we go through a either from the left or from the right. 编辑:试图澄清:好了,所以我们要经过a无论是从左边或右边。 If we encounter 0 , we no nothing. 如果我们遇到0 ,我们什么也没有。 If we counter 1 , we take the value at the corresponding index of b . 如果我们计数器1 ,我们取相应指数b的值。 For example, going from the left, we do nothing for two 0 s, then we find 1 so we take the corresponding 1 from b , we find another 0 in a and do nothing and then we find another 1 in a and take the corresponding 0 from b . 例如,从左边开始,我们什么都不做两个0秒,然后我们找到1所以我们从b取出相应的1 ,我们在a找到另一个0并且什么都不做,然后我们在a找到另一个1并取相应的b来自0

EDIT: Another way to put it is like this: Shift a to the right and read out the value (is this possible?). 编辑:另一种方式把它是这样的:移a向右并读出值(这可能吗?)。 If it's 1 , we shift b to the right, read the value, store it to a result variable r and shift r to the right. 如果它是1 ,我们将b向右移动,读取值,将其存储到结果变量r并向右移动r If it's 0 , we shift b to the right, forget the value and do nothing with r . 如果它为0 ,我们将b向右移动,忘记值并且不对r做任何事情。

EDIT: I'll elaborate a bit on the purpose to try and clarify what I want to do. 编辑:我会详细说明目的,试图澄清我想做什么。 We have a set of boolean variables (say 5 to agree with our example). 我们有一组布尔变量(比如说5与我们的例子一致)。 The variable b represents an array of their states according to some indexing. 变量b根据一些索引表示它们的状态数组。 The 1 s in variable a represent the indices, namely 2 and 4 in our example, of the boolean variables in our system that matter to a certain boolean variable (say the 0th). 变量a1表示我们系统中的索引,即我们示例中的2和4,与某个布尔变量(比如第0个)有关。 The values of the 2nd and 4th boolean variables form one of the possible inputs to a truth table associated with the 0th variable. 第2和第4个布尔变量的值构成与第0个变量关联的真值表的可能输入之一。

Any suggestions? 有什么建议?

EDIT: Right now, what I'm doing is this. 编辑:现在,我正在做的是这个。 Suppose we have a system with 5 boolean variables, indexed $0,1,2,3,4$. 假设我们有一个包含5个布尔变量的系统,索引为$ 0,1,2,3,4 $。 Suppose that the 0th variable is a function of the 2nd and 4th variables and has a the truth table of AND, ie 假设第0个变量是第2个和第4个变量的函数,并且具有AND的真值表,即

2 | 4 |Output for 0

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

I always keep the table sorted in this fashion, so I don't really need the left part of the table. 我总是以这种方式对表进行排序,所以我真的不需要表的左侧部分。 The right part of the table is implemented as a byte[] array. 该表的右侧部分实现为byte[]数组。 To find the output, I simply take the integer representation of the input read as a binary number. 为了找到输出,我只是将输入读取的整数表示作为二进制数。 Eg the input 10 is 2, so my output is the value at index 2 in my byte[] array. 例如,输入10是2,所以我的输出是我的byte[]数组中索引2的值。 To find the input, I need the part of the current state of my system which corresponds to variable in question, namely the 0th. 为了找到输入,我需要系统当前状态的一部分,它对应于有问题的变量,即0。 That is, I want the values of the 2nd and 4th variables, read in that order. 也就是说,我想要第二个和第四个变量的值,按顺序读取。

Thus: 从而:

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] 

By the way, "10100" is 20 not 24 顺便说一句,“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")
    }
}

You still end up with a loop, so this really only saves memory. 你仍然最终得到一个循环,所以这只会节省内存。

This is only pseudo code, so no guarantees for completeness nor correctness. 这只是伪代码,所以不保证完整性和正确性。

r = 0

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

Given these inputs ... 鉴于这些投入......

a = 00101
b = 10100
bits = 5

the algorithm behaves as follows. 算法表现如下。 Initialize the result. 初始化结果。

r = 0

Take the last bit, which is at i=0 . 取最后一位,即i=0 In order to do so shift to the position i in and kick rest of digits with an and operation like this: & 1 . 为了做到这一点,转移到i所在的位置并使用和这样的操作踢数字的其余部分: & 1 Do this for both a and b . ab执行此操作。 Then check if the filter condition is true, in this case it means when a has a 1 on the last bit. 然后检查,如果过滤条件为真,在这种情况下,它是指当a1上的最后一位。

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

The code can be cleaned up with two functions, like this: 可以使用两个函数清理代码,如下所示:

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));
  }
}

It's unlikely that these operations are going to be a bottleneck for your program. 这些操作不太可能成为您程序的瓶颈。 So my advice is just use an array of booleans -- don't bother with bit-by-bit operations, it's going to make your program harder to understand and modify. 所以我的建议只是使用一系列布尔值 - 不要为逐位操作而烦恼,这会让你的程序更难理解和修改。

If you are really worried about execution time spent on these operations, do some careful benchmarking or profiling before trying to optimize it. 如果您真的担心在这些操作上花费的执行时间,请在尝试优化之前进行一些仔细的基准测试或分析。 My guess is that will show there's nothing to gain by modifying that code. 我的猜测是,这将显示修改该代码没有任何好处。

Your description is vague, but it is emerging from the obscurity that this is not a bitwise operation at all. 你的描述含糊不清,但从默默无闻中可以看出,这根本不是一个按位操作。 In which case my original suggestion that you provide a truth table holds good, and in fact that's how you should implement it as well: with a table lookup. 在这种情况下,我提供真值表的原始建议很好,事实上,你应该如何实现它:使用表查找。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM