I have 2 byte arrays, each containing 4 bytes (byte1[], byte2[]) and I want to XOR them to create a new 4 byte array (byte3[]) how would I do this?
(or even do each byte at a time then put them into the new array)
You need to convert them to integers (no loss, primitive widening), do the XOR, then convert the resulting int back to a byte using a bit mask.
// convert to ints and xor
int one = (int)byte1[0];
int two = (int)byte2[0];
int xor = one ^ two;
// convert back to byte
byte b = (byte)(0xff & xor);
Example
String a = "10101010";
String b = "01010101";
String expected = "11111111"; // expected result of a ^ b
int aInt = Integer.parseInt(a, 2);
int bInt = Integer.parseInt(b, 2);
int xorInt = Integer.parseInt(expected, 2);
byte aByte = (byte)aInt;
byte bByte = (byte)bInt;
byte xorByte = (byte)xorInt;
// conversion routine compacted into single line
byte xor = (byte)(0xff & ((int)aByte) ^ ((int)bByte));
System.out.println(xorInt + " // 11111111 as integer");
System.out.println(xorByte + " // 11111111 as byte");
System.out.println(aInt + " // a as integer");
System.out.println(bInt + " // b as integer");
System.out.println((aInt ^ bInt) + " // a ^ b as integers");
System.out.println(aByte + " // a as byte");
System.out.println(bByte + " // b as byte");
System.out.println(xor + " // a ^ b as bytes");
Prints the following output
255 // 11111111 as integer
-1 // 11111111 as byte
170 // a as integer
85 // b as integer
255 // a ^ b as integers
-86 // a as byte
85 // b as byte
-1 // a ^ b as bytes
You can use the xor operation on bytes. It's the caret (^).
Example:
byte3[0] = (byte) (byte1[0] ^ byte2[0]);
This will work for equal or different size byte array as well.
/** Return XOR of two byte array of different or same size. */
public static byte[] xor(byte[] data1, byte[] data2) {
// make data2 the largest...
if (data1.length > data2.length) {
byte[] tmp = data2;
data2 = data1;
data1 = tmp;
}
for (int i = 0; i < data1.length; i++) {
data2[i] ^= data1[i];
}
return data2;
}
Java has a XOR operator in the form of ^. Just XOR each byte with each subsequent byte and put them in the new array.
Related
Given an array filled with 4 bytes inside (R,G,B,A), I'm trying to translate this array full of 4 8bits numbers into its translation in 32bits. To be more clear, if I get an array such as:
byte[] tab = {1,2,3,4};
with translated in binary in 8bit :
1 = 0b00000001
2 = 0b00000010
3 = 0b00000011
4 = 0b00000100
Then, my method should return a byte array such as :
newTab = {00000001_00000010_00000011_00000100};
For some reason, I'm trying to do this without using a String to concatenate the bytes.
I've already tried something with binary operators such as <<, >> or |, but without success...
So far, my code looks like this :
byte[] tab = {1,2,3,4};
int tmp,tabToInt = 0;
for (int x = 0 ; x < tab.length ; ++x){
tmp = tmp << (tab.length - 1 - x)*8;
byteToInt = byteToInt | tmp;
}
return tabToInt;
But it didn't seem to work, even less with negatives bytes... (like -1 = 0b11111111)
Thanks in advance for your answers!
You can use ByteBuffer like this.
byte[] tab = {1, 2, 3, 4};
int tabToInt = ByteBuffer.wrap(tab).getInt();
System.out.println("decimal = " + tabToInt);
System.out.println("binary = " + Integer.toBinaryString(tabToInt));
System.out.println("hexadecimal =" + Integer.toHexString(tabToInt));
output
decimal = 16909060
binary = 1000000100000001100000100
hexadecimal =1020304
ByteBuffer can do it, but only if you get passed at least 4 bytes.
The problem with your code is two-fold:
I think you typoed somewhere, your code doesn't even compile. I think you meant tmp = tab[x] << (tab.length - 1 - x)*8;. Your snippet never does anything with tab other than ask for its length.
Negative numbers extend, and java will convert any byte or short to an int the moment you do any math to it. So, 0b1111 1111, if you try to do e.g. << 8 on that, java first turns that -1 byte into a -1 int (so that's now 32 1 bits), and then dutifully left shifts it by 8, so now that's 24 1 bits, followed by 8 0 bits. You then bitwise OR that into your target, and thus now the target is mostly 1 bits. To convert a byte to an int without "sign extension", (b & 0xFF does it:
byte b = (byte) 0b1111_1111;
assert b == -1; // yup, it is
int c = b; // legal
assert c == -1; // yeah, still is. uhoh. That's...
int d = 0b11111111_11111111_11111111_11111111;
assert c == d; // yeah. We don't want that.
int e = (b & 0xFF);
assert e = 255;
int f = 0b0000000_0000000_0000000_11111111;
assert e == f; // yes!
I have two bytes of data. I converted each of them to Uint8 then I produced a Uint16 from them.
How I can produce two's complement of this Uint16 number?
I've tried uInt16 = ~uInt16 + 1 but the code produces 32bit integer and I want it to stay a 16bit Integer.
byte firstByte, secondByte;
int firstUint8, secondUint8, uInt16;
firstByte = buffer[index];//get first byte from buffer
secondByte = buffer[index + 1];//get second byte from buffer
firstUint8=firstByte & 0xFF;//produce Uint8
secondUint8 = secondByte & 0xFF;//produce Uint8
uInt16 = 256 * firstUint8 + secondUint8;//create Uint16 from these to Uint8
twosComplementOfUInt16=~number+1; //produce 32 bit integer but I want int16
Java is not the best programing language to work with bits. But if you want you can read the documentation to see how the number are represented in java; how to work with bytes or you can do a tutorial.
As observation the (~ and +) returns an integer
public static void main(String[] args) {
int uint8 = 0xff;
int uint16 = 0xffff;
long uint32 = 0xffffffff;
int one = 0x0001;
int ten = 0x000A;
int twoComplementOfTen = 0xFFF6;
int computedTwoComplementOfTen = ~ten + one;
int revertTwoComplementOfTen = ~twoComplementOfTen + one;
System.out.printf("One = 0x%04X \n", one);
System.out.printf("ten = 0x%04X \n", ten);
System.out.printf("~ten + one = 0x%04X \n", twoComplementOfTen);
System.out.printf("Computed ~ten + one = 0x%04X \n", computedTwoComplementOfTen);
System.out.printf("~twoComplementOfTen + one = 0x%04X \n", revertTwoComplementOfTen);
System.out.printf("Computed ~ten + one with uint16 mask = 0x%04X \n", uint16 & computedTwoComplementOfTen);
System.out.printf("~twoComplementOfTen + one with uint16 mask = 0x%04X \n", uint16 & revertTwoComplementOfTen);
}
Output:
One = 0x0001
Ten = 0x000A
~ten + one = 0xFFF6
Computed ~ten + one = 0xFFFFFFF6
~twoComplementOfTen + one = 0xFFFF000A
Computed ~ten + one with uint16 mask = 0xFFF6
~twoComplementOfTen + one with uint16 mask = 0x000A
The "twos complement" of a number is obtained by negation, at least on machines that use twos-complement representation of integers, which is true for nearly all modern hardware and is true for the Java virtual machine.
short x;
...set value of x...
x = -x;
In twos-complement hardware and in the Java virtual machine, negation is equivalent to invert and add one. The following demonstrates this:
Example:
public class Foo {
public static void main(String[] args) {
short n = 2; n = -n;
System.out.println(n);
short m = 2; m = ~m + 1;
System.out.println(m);
}
}
The output from the above is identical for m and n.
If you find it necessary to use 32-bit ints for the value then you can simply mask the result to 16 bits.
int uint16 = some_value;
int compl = -uint16 & 0xffff;
Is this the correct way to bit shift into a char?
char value = (char)((array[offset] << 9) + (array[offset + 1]));
If not, please correct me.
Bytes in Java are a bit tricky.
They don't go from 0 to 255 like you might be used to from other languages. Instead, they go from 0 to 127 and then from -128 to -1.
This means, that all bytes in your byte array that is below 128 will be converted into the correct char with this code:
char value = (char)((array[offset] << 8) + (array[offset + 1]));
But if the byte value is above 127, you'll probably get results you didn't expect.
Small example:
class test {
public static void main(String[] args) {
byte b = (byte)150;
char c = (char)b;
int i = (int)c;
System.out.println(b);
System.out.println(c);
System.out.println(i);
}
}
Will output this:
-106
οΎ–
65430
Not exactly what you might expect. (Depending of course how well you know Java).
So to properly convert 2 bytes into a char, you'd probably want a function like this:
char toChar(byte b1, byte b2) {
char c1 = (char)b1;
char c2 = (char)b2;
if (c1<0) c1+=256;
if (c2<0) c2+=256;
return (char)((c1<<8)+c2);
}
---EDIT: I am not allowed to use any packages, or prewirtten methods. And no worries, i don't want you to make my "homework", i just need a little hint!---
I found these interesting Algorithms. I want to use the method bitwiseAdd. My problem is, that the left shift operator returns a value that is not binary...
I understand the algorithm, but i am quite a beginner. So here is the "program". I implemented extra outputs to find the issue. I think it must be the left shift operator. Here is the code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
class Addition1
{
public static int first;
public static int second;
public static void main(String args[]) throws Exception
{
BufferedReader userInput = new BufferedReader(newInputStreamReader(System.in));
System.out.println("Geben sie den ersten Summanden ein!");
first = Integer.parseInt(userInput.readLine());
System.out.println("Geben sie den zweiten Summanden ein!");
second = Integer.parseInt(userInput.readLine());
bitwiseAdd(first, second);
}
public static void bitwiseAdd(int n1, int n2)
{
int x = n1, y = n2;
int xor, and, temp;
and = x & y;
xor = x ^ y;
System.out.println("x: " + x);
System.out.println("y: " + y);
System.out.println("and: " + and);
System.out.println("xor: " + xor);
System.out.println("Schleife:");
while (and != 0)
{
and <<= 1;
System.out.println("and <<= 1: " + and);
temp = xor ^ and;
System.out.println("temp = xor ^ and: " + temp);
and &= xor;
System.out.println("and &= xor: " + and);
xor = temp;
System.out.println("xor = temp: " + xor);
}
System.out.println("Ergebnis: " + xor);
}
}
Here is the output (+annotations) of the program for n1= 1001 and n2=1101:
Geben sie den ersten Summanden ein! (means: type in first value)
1001
Geben sie den zweiten Summanden ein! (means: type in second value)
1101
x: 1001
y: 1101
and: 73 (java might interpret x and y as non binary)
xor: 1956
Schleife: (means: loop)
and <<= 1: 146
temp = xor ^ and: 1846
and &= xor: 128
xor = temp: 1846
and <<= 1: 256
temp = xor ^ and: 1590
and &= xor: 256
xor = temp: 1590
and <<= 1: 512
temp = xor ^ and: 1078
and &= xor: 512
xor = temp: 1078
and <<= 1: 1024
temp = xor ^ and: 54
and &= xor: 1024
xor = temp: 54
and <<= 1: 2048
temp = xor ^ and: 2102
and &= xor: 0
xor = temp: 2102
Ergebnis: 2102 (means: result)
I would be happy about any help! :)
Have a nice day,
Cortex
The values in your program were never interpreted as binary. You are actually adding the decimal values 1001 and 1101, and correctly summing them to 2102. Also, the binary representations of decimal 1001 and 1101 are
1001: 00000011 11101001
1101: 00000100 01001101
When anded, you get decimal 73:
73: 00000000 01001001
If you want to interpret those numbers as binary, use a radix of 2 in Integer.parseInt, for example:
first = Integer.parseInt(userInput.readLine(), 2);
To output a number in a binary format, use Integer.toBinaryString, for example:
System.out.println("Ergebnis: " + Integer.toBinaryString(xor));
You are trying to write a virtual machine inside a virtual machine inside the real machine, which might itself be a virtual machine. No wonder there is confusion.
You will need to represent you data as array of bool (or int or char etc).
bool [] operand1 = new bool [8];
bool [] operand2 = new bool [8];
bool [] leftShift (bool [] operand)
{
bool [] result = new bool [operand.length];
for (int i=8; i>1; i++)
{
result[i] = operand[i-1];
}
return result;
}
bool [] and (bool [] operand1, bool [] operand2)
{
int max, min;
if (operand1.length > operand2.length) {
max = operand1.length;
min = operand2.length;
}
else {
max = operand2.length;
min = operand1.length;
}
bool [] result = new bool [max];
for (int i = 0; i<min;i++)
{
result[i] = operand1[i] && operand2[i];
}
return result;
}
I used first = 1001; second = 1101; bitwiseAdd(first, second); in the main method, but still the program interprets these as decimal numbers (which is logical).
When you write a literal in a Java program, the syntax of the literal tells Java how to interpret it.
12345 // decimal
012345 // octal
0x1234 // hexadecimal
0b1001 // binary
There is no guesswork here. The syntax you use tells the Java compiler.
For more info: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
(The only slightly tricky thing is that a leading non-significant zero means that the number is octal not decimal. That is an regrettable (IMO) carry-over from the C programming language. It does trip up some people.)
Do you know how i can change that?
Yea ... if you want to express the numbers as binary in the source code, use binary literals.
The thing you need to get thoroughly into your head is that binary / octal / decimal / hexadecimal are all about getting numbers from or presenting numbers to the user (or programmer). Internally, they all turn into the same thing. The int type (and other integral types) are agnostic of decimal, binary and so on. There is only one type, and the arithmetic and bitwise operators on int have only one meaning.
I'm trying to create a new byte knowing a certain amount of bits
char prostie1 = theRepChars[j-3];
char prostie2 = theRepChars[j-2];
char prostie3 = theRepChars[j-1];
char prostie4 = theRepChars[j];
String prostiaMare = prostie4 + prostie3 + prostie2 + prostie1 + "";
Byte theChar = new Byte(prostiaMare);
When i do this I get a NumberFormatException value 196.
I have no idea what might be my problem
--EDIT--
Ok I think I might have to give some more details since I wasn't very clear. I'm trying to do an Uuencode algorithm and by following the logic of the algorithm I should stop my byte having a value bigger than 194. Here is a bunch of my code.
if(my_chars.length % 3 == 0)
{
for(int x = 0; x < my_chars.length; x++)
{
if((x+1) % 3 == 0)
{
char first = my_chars[x-2];
char second = my_chars[x-1];
char third = my_chars[x];
int n = (((first << 8) | second) << 8) | third;
String theRep = Integer.toBinaryString(n);
while(theRep.length() < 24 - 1)
{
theRep = 0 + theRep;
}
//0 padded theRep
for(int j = 0; j < theRepChars.length; j++)
{
if((j+1) % 4 == 0)
{
char prostie1 = theRepChars[j-3];
char prostie2 = theRepChars[j-2];
char prostie3 = theRepChars[j-1];
char prostie4 = theRepChars[j];
String prostiaMare = prostie4 + prostie3 + prostie2 + prostie1 + "";
System.out.println(prostiaMare);
}
}
}
}
}
And trying to create a new byte with the value that prostiaMare has gives me the numberFormatException. I'm not sure if I have not followed the algorithm right ( http://www.herongyang.com/encoding/UUEncode-Algorithm.html )
196 is outside the range of byte, a signed value. Bytes can range from -128 to 127.
I'm not sure why you're casting to String. If you just want a byte with bits equivalent those of the sum of the four chars, cast directly to byte:
(byte) (prostie4 + prostie3 + prostie2 + prostie1)
If you intended to construct a String from the four chars, you are not currently doing that. Use:
"" + prostie4 + prostie3 + prostie2 + prostie1
and, if the result is in the range of a byte, you can create a byte as you have been.
Bytes are signed in Java. Which means a byte, which is 8 bits long, has a minimum value of -2^7 (-128) and a max value of 2^7 - 1 (127). Java has no unsigned primitive types apart from char (unsigned, 16bit).
Therefore 196 is unparseable --> NumberFormatException.
You don't have much to work around this except to read into a larger type and do & 0xff to obtain the byte:
final int i = Integer.parseInt(theString);
final byte b = (byte) (i & 0xff);
Or do yourself a favour and use Guava, which has UnsignedBytes:
final byte b = UnsignedBytes.parseUnsignedByte(theString);
But it appears that you want to do comparisons anyway; so just use a larger type than byte. And no, this won't waste memory: don't forget about alignment.
As mentioned in the docs
An exception of type NumberFormatException is thrown if any of the following situations occurs:
The first argument is null or is a string of length zero.
The radix is either smaller than Character.MIN_RADIX or larger than Character.MAX_RADIX.
Any character of the string is not a digit of the specified radix, except that the first - character may be a minus sign '-' ('\u002D') provided that the string is longer than length 1.
The value represented by the string is not a value of type byte.
In your case its the last case since 196 cant be represented as byte..The valid range is -128 to 127