【问题标题】:Issues with reversing bit shifts that roll over the maximum byte size?反转移位超过最大字节大小的问题?
【发布时间】:2010-04-09 17:09:11
【问题描述】:

我正在尝试对二进制字符串进行简单的剖腹产,并且它需要是可逆的。我已经用这种方法做到了..

public static String cShift(String ptxt, int addFactor)
    {
        String ascii = "";
        for (int i = 0; i < ptxt.length(); i+=8)
        {
            int character = Integer.parseInt(ptxt.substring(i, i+8), 2);
            byte sum = (byte) (character + addFactor);
            ascii += (char)sum;
        }
        String returnToBinary = convertToBinary(ascii);
        return returnToBinary;
    }

这在某些情况下可以正常工作。但是,我认为当它翻转可以用一个字节表示时,它是不可逆转的。在12addFactor 测试字符串"test!22*F " 上,字符串变得不可逆。为什么会这样?我该如何阻止它?

编辑:为了澄清起见,测试字符串在传入之前被转换为二进制。这里是 convertToBinary

public static String convertToBinary(String str)
    {
        char [] array = str.toCharArray();
        String binaryToBeReturned = "";

        for (int i = 0; i < str.length(); i++)
        {
            String binary = Integer.toBinaryString((int)array[i]);
            binary = padZeroes(binary);
            binaryToBeReturned += binary;
        }
        return binaryToBeReturned;
    }

当我以 12 的 cShift 运行此程序,然后以 -12 的 cShift 进行反转时,我得到了这个...

01110100011001010111001101110100001000010011001000110010010001100010101000100000
111111111000000001110001011111111111111110000000001011010011111000111110010100100011011000101100
ÿ?qÿ?->>R6,
ÿótesÿót!22F*

第一个字符串只是将测试字符串转换为二进制。第二个字符串是二进制 cShift 的结果。第三个字符串是这个转换成ascii的结果,第四个字符串是在cShift上用-12反转并转换成ascii的结果。

我很清楚,不知何故,从翻转中添加了额外的位,我不完全确定如何处理它。谢谢。

【问题讨论】:

  • 什么是二进制字符串?我想我看不出"test!22*F " 是如何二进制的。
  • 看来这个问题与OP的另一个问题有关:stackoverflow.com/questions/2608888/…
  • 是的,在这种情况下,问题当前是错误的。你不能使用那个测试字符串。

标签: java type-conversion


【解决方案1】:

扩大到char时需要屏蔽byte,否则符号位会被扩展。

ascii += (char)(sum & 0xFF)

如果您不想要符号扩展,则此掩码模式适用于加宽有符号数字类型。

anInt = aByte & 0xFF;
anInt = aShort & 0xFFFF;
aLong = anInt & 0xFFFFFFFFL; // notice the L

这里有一个例子来说明:

byte b = -1; // 0xFF
char ch = (char) b; // 0xFFFF
int i = ch;
System.out.println(i); // prints "65535", which is 0xFFFF

byte b = -1; // 0xFF
char ch = (char) (b & 0xFF); // 0xFF
int i = ch;
System.out.println(i); // prints "255", which is 0xFF

这里有一个教训。如果你读过Java Puzzlers,你会看到一些围绕符号扩展的hooplas。书中的这个谜题与我上面的那个谜题基本相同,但可能更令人困惑:

// Java Puzzlers, Puzzle 6: Multicast
System.out.println((int) (char) (byte) -1); // prints 65535

有两种方法可以解决这个问题:

  • 避免使用byteshort。您很少需要这样做。
  • 如果您与他们一起工作,请始终警惕戴口罩的必要性。
  • bytechar 总是很棘手,因为:
    • 虽然charbyte 宽...
    • char 是未签名的,而 byte 是!!!
    • 因此,这不是简单的拉宽转换,而是拉宽-收窄转换!

JLS 5.1.4 Widening and Narrowing Primitive Conversions

以下转换结合了扩大和缩小的原始转换:

  • bytechar

首先,byte 通过加宽基元转换转换为int,然后通过缩小基元转换将生成的int 转换为char


其他参考

【讨论】:

  • 这是真的,Terri,你确定你在转换回来的时候是在做上面的功能吗?
  • 我不认为有不同的转换功能;如果他cShiftN,那么他稍后只需cShift-N 转换回来。
  • 啊 - 我完全忘记了 char 在 Java 中是 2 个字节。不错的收获。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-04
  • 2022-04-20
  • 1970-01-01
  • 1970-01-01
  • 2017-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多