撤消按位运算

时间:2017-07-07 18:24:34

标签: java bit-manipulation bitwise-operators

我有一个由另一个程序员编写的Java函数,它使用按位操作。我需要一个能够撤消进程的函数(如果可能的话)。也许你们中的一些人比我对这些运营商更精明。以下是需要撤消的内容:

public void someFunc(int[] msg, int[] newMsg) {
    int i = SOME_LENGTH_CONSTANT;
    for (int j = 0; j < newMsg.length; j++) {
        // msg[i] Shift left by 8 bits bitwise or with next msg[i+1]
        // then bitwise not (~) and bitwise and with $FFF
        newMsg[j] = (~(((msg[i] & 0x0f) << 8) | (msg[i + 1]))) & 0xfff;
        i += 2;
    }
}

2 个答案:

答案 0 :(得分:1)

我的版本,不料:

public void undoFunc(int[] newMsg, int[] original) {
        int i = SOME_LENGTH_CONSTANT; // starting point
        for (int j = 0; j < newMsg.length; j++) { // Iterate over newMsg

            original[i] = ~((newMsg[j]&0xff00)>>8)&0x000f; // &0x000f to get rid of "mistakes" when NOT-ing
            original[i+1] = (~(newMsg[j]&0x00ff)) & 0xff;
            // i = initial value + 2 * j
            i+=2;
        }
    }

您的代码有什么作用?
输入是整数数组。每两个值用于在&#39;输出中创建一个值。 (newMsg)数组。

  1. 首先,它删除输入中第一个值的左四位。
  2. 然后它&#34;滚动&#34;该值为8位于左侧并将零置于空白点。
  3. 它将第二个值msg[i+1]放在最右边四位的零中。
  4. 它否定了价值,所有零都变为零,所有零变为零。
  5. 当4)完成时,最左边的4个位(在步骤1中清除)变为1,所以用&0x0FFF撤消它。
  6. 迭代示例:

    msg[i] ==   1010'1011
    msg[i+1] == 0010'0100
    
    1) 1010'1011           ->           0000'1011
    2) 0000'1011           -> 0000'1011'0000'0000
    3) 0000'1011'0000'0000 -> 0000'1011'0010'0100
    4) 0000'1011'0010'0100 -> 1111'0100'1101'1011
    5) 1111'0100'1101'1011 -> 0000'0100'1101'1011
    
    newMsg[j] == 0000'0100'1101'1011 == 0x04DB (I think, from memory)
    

    我的代码的作用: 获得(以前的)msg[i+1]的值很容易,它与最右边的8位相反/ NOT。因为否定它会将所有前导零变为1,所以AND0xffmsg[i]进行对比。 获得(曾经是)&0x000f的价值更加困难。首先向左滚动最左边的8位。然后我否定了价值。但是四个未使用/丢失的位现在是1,我希望OP希望这些为零,所以我0000'0100'1101'1011它。

    注意:我使用带有前导零的六边形使其更清晰。这些都没有必要 注意:为了便于阅读,我将二进制数分成四位。因此0b实际上是{0000010011011011msg[i+1]

    msg[i]的值已恢复,但&的最左边四位丢失。

    Fwew。

    原帖:

    在您的代码中,您使用&a所做的是,所有人都同意这些比特&#39; (当来自字节1的位和来自字节b的同等有效位都是1)进入0 s而其余位进入& s。这意味着,正如@Mike Harris所说,不同意的所有内容都会消失。

    示例1010 & 0110 = 1 & 0 => 0 0 & 1 => 0 1 & 1 => 1 0 & 0 => 0 = 0010 (和操作):

    a

    如您所见,只保留字节1的第二和第三最高有效位(或零包含第一和第二最低有效位)(第4位/#0是&#39;运气&# 39;),因为它们是字节b中的1

    您可以反转代码中b字节fff的所有位(其中一个为1111 1111 1111,或二进制为1111 1111 1111 == 000000000...00111111111111,但请记住所有位删除比第一个更重要,因为<java jar="${eclipse.equinox.launcher.plugin}" fork="true" failonerror="true"> <arg value="-application"/> <arg value="org.eclipse.ant.core.antRunner"/> <arg value="-buildfile"/> <arg value="${eclipse.pde.build.plugin}/scripts/productBuild/productBuild.xml"/> <arg value="-Dbuilder=${build.directory.projectroot}"/> </java> )。但这不会逆转它,只能根据逆转它的目的而起作用。

    More about the AND Bitwise operation on Wikipedia.

答案 1 :(得分:0)

我只想尝试这样做,这是我尝试的结果。

一开始我将表达式拆分为单个操作:

  1. int t1 = msg[i] & 0x0f;

    除了最后4位,我们失去了所有。

  2. int t2 = t1 << 8;

    通过移位t1清除低8位。

  3. int t3 = t2 | msg[i + 1];

    我们应该了解m[i + 1]是否大于255(特别是m[i + 1] & 0xf00 > 0),我们无法恢复m[i]的低4位,因为它们会被不可逆转地覆盖。

  4. int t4 = ~t3;

    只是否定。

  5. newMsg[j] = t4 & 0xfff;

    低12位。

  6. 只是按相反的顺序执行了这些步骤:

    public static void someFuncRev(int[] msg, int[] newMsg) {
        for (int i = 0; i < msg.length; ++i) {
            newMsg[2 * i] = (~msg[i] >> 8) & 0xf; // take 11-8 bits
            newMsg[2 * i + 1] = ~msg[i] & 0xff; // take 7-0 bits
        }
    }
    

    我假设SOME_LENGTH_CONSTANT == 0。调整常数很容易。

    因此,当msg内的值<= 15时,上述函数将恢复初始序列。 在值> 15且<= 255的情况下,对于msg[i],我们只能恢复4位,msg[i + 1]完全恢复。 如果值> 255,我们无法恢复msg[i],因为它是由msg[i + 1]的位进行校正(在第3点看上面);可以恢复8位msg[i + 1]

    我希望这会对你有所帮助。