循环移位:字节数组(byte[])实现二进制串的循环移位
最近去公司实习了。公司的主业是网络安全,先说一个:密码学中的移位都是循环移位。现在用字节数组byte[]存储二进制串,1024个二进制数字就是128个字节,byte[128],如何实现这样的二进制串的循环移位呢?
网上只有对数组的移位,比如int[],char[],string,但直接套用byte[]是不符合要求的!我自己感觉这套东西是我全网首发哈哈哈哈哈哈哈哈哈哈哈!(因为我自己已经翻来覆去百度过很久了哈哈哈哈哈哈)
感谢徐利军老师提供的算法框架和王啸赟同学的提点。已通过手算验证!
算法核心Java代码如下:(屏蔽掉的代码就是原本出问题的地方,大家注意右移运算中补1/0的问题)
【2018年3月16日17:25:08】原来的算法前的判断逻辑一直隐约觉得不对,今天算了一下午改正了bug,现在全部放上来……
import java.util.Arrays;
public class Byte_SHIFT { //循环移位
public static void main(String[] arg) { //测试
byte[] test = new byte[128];
test[0] = 0;
for (int i = 1; i < 128; i++) {
test[i] = 1;
}
System.out.println(Arrays.toString(test));
test = leftShift(test, 250);
System.out.println(Arrays.toString(test));
}
public static byte[] hexStringToByte(String hex) {
int len = (hex.length() / 2);
byte[] result = new byte[len];
char[] achar = hex.toCharArray();
for (int i = 0; i < len; i++) {
int pos = i * 2;
result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
}
return result;
}
private static int toByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
private static void RotateRightOne(byte[] bytes) {
byte valBit;
valBit = (byte) (bytes[bytes.length - 1] << (byte) (7));
for (int i = bytes.length - 1; i > 0; i--) {
bytes[i] = (byte) ((bytes[i] >> (byte) (1)) | (bytes[i - 1] << (byte) (7)));
}
bytes[0] = (byte) ((bytes[0] >> (byte) (1)) | valBit);
}
public static byte[] rightShift(byte[] bytes, int X) { //X<bytes.length
int byte_move;
int binary_move;
if (X % 1024 == 0) {
return bytes;
} else {
if (X > 1024) {
while (X > 1024) {
X -= 1024;
}
}
byte_move = (X - X % 8) / 8;
byte[] new_bytes = new byte[128];
System.arraycopy(bytes, 0, new_bytes, byte_move, bytes.length - byte_move);
System.arraycopy(bytes, bytes.length - byte_move, new_bytes, 0, byte_move);
binary_move = X % 8;
if (binary_move == 0) {
return new_bytes;
} else {
cyclic_right_shift(new_bytes, binary_move);
return new_bytes;
}
}
}
public static byte[] leftShift(byte[] bytes, int X) { //X<bytes.length
int byte_move;
int binary_move;
if (X % 1024 == 0) {
return bytes;
} else {
if (X > 1024) {
while (X > 1024) {
X -= 1024;
}
}
byte_move = (X - X % 8) / 8;
byte[] new_bytes = new byte[128];
System.arraycopy(bytes, byte_move, new_bytes, 0, bytes.length - byte_move);
System.arraycopy(bytes, 0, new_bytes, bytes.length - byte_move, byte_move);
binary_move = X % 8;
if (binary_move == 0) {
return new_bytes;
} else {
cyclic_left_shift(new_bytes, binary_move);
return new_bytes;
}
}
}
private static void cyclic_left_shift(byte[] bytes, int X) {
/* byte first_byte_begin_bit = (byte) (bytes[0] >> (byte) (8 - X));
if (first_byte_begin_bit < 0) {
byte temp = (byte) ((byte) (-128) >> (byte) (8 - X - 1));
first_byte_begin_bit = (byte) (first_byte_begin_bit ^ temp);
}
for (int i = 0; i < bytes.length - 1; i++) {
byte A = (byte) (bytes[i] << (byte) (X));
byte B = (byte) (bytes[i + 1] >> (byte) (8 - X));
if (B < 0) {
byte temp = (byte) ((byte) (-128) >> (byte) (8 - X - 1));
B = (byte) (B ^ temp);
}
bytes[i] = (byte) (A | B);
}
byte A = (byte) (bytes[bytes.length - 1] << (byte) (X));
bytes[bytes.length - 1] = (byte) (A | first_byte_begin_bit);*/
int first_byte_begin_bit = bytes[0] >>> 8 - X;
for (int i = 0; i <bytes.length-1; i++)
{
int A=(bytes[i]&0xff)<< X;
int B=bytes[i + 1] >>> (8 - X);
bytes[i] = (byte) (A|B);
}
bytes[bytes.length-1]=(byte)((bytes[bytes.length-1]&0xff)<<X);
bytes[bytes.length-1] = (byte)(bytes[bytes.length-1]|first_byte_begin_bit);
}
private static void cyclic_right_shift(byte[] bytes, int X) {
/* byte end_byte_final_bit = (byte) (bytes[bytes.length - 1] << (byte) (8 - X));
for (int i = bytes.length - 1; i > 0; i--) {
byte A = (byte) (bytes[i] >> (byte) (X));
byte B = (byte) (bytes[i - 1] << (byte) (8 - X));
if (A < 0) {
byte temp = (byte) ((byte) (-128) >> (byte) (X - 1));
A = (byte) (A ^ temp);
}
bytes[i] = (byte) (A | B);
// bytes[i] = (byte) ((byte) ((bytes[i] >> (byte) (X))) | (byte) ((bytes[i - 1] << (byte) (8 - X))));
}
byte A = (byte) (bytes[0] >> (byte) (X));
if (A < 0) {
byte temp = (byte) ((byte) (-128) >> (byte) (X - 1));
A = (byte) (A ^ temp);
}
bytes[0] = (byte) (A | end_byte_final_bit);*/
//bytes[0] = (byte) ((byte) ((bytes[0] >> (byte) (X))) | end_byte_final_bit);
int end_byte_end_bit = bytes[bytes.length - 1] << 8 - X;
for (int i = bytes.length - 1; i > 0; i--)
{
int A=(bytes[i]&0xff)>>> X;
int B=bytes[i - 1] << 8 - X;
bytes[i] = (byte) (A|B);
}
bytes[0]=(byte)((bytes[0]&0xff)>>>X);
bytes[0] = (byte)(bytes[0]|end_byte_end_bit);
}
}