I want to use bitwise operators between strings(stirngs has not the same length) in Java.
Actually, in case that I have two Strings
e.g s1=test s2=sampleJAVA
I convert strngs to binary:
s1Binary=01110100 01100101 01110011 01110100
s2Binary=01110011 01100001 01101101 01110000 01101100 01100101 01001010 01000001 01010110 01000001
And I want to calculate two bitwise operators
s1Binary | s2Binary
s1Binary & s2Binary
I tried for two strings:
String s1 = "test";
byte[] a = s1.getBytes();
String s1Binary = "";
for (int i = 0; i < a.length; i++) {
s1Binary = s1Binary + String.format("%8s", Integer.toBinaryString(a[i] & 0xFF)).replace(' ', '0');
}
/////// s2 /////
String s2 = "sampleJAVA";
byte[] b = s2.getBytes();
String s2Binary = "";
for (int i = 0; i < b.length; i++) {
s2Binary = s2Binary + String.format("%8s", Integer.toBinaryString(b[i] & 0xFF)).replace(' ', '0');
}
But I stuck there because I have two strings with different (binary) length
You can use BigInteger like this.
String s1Binary = "01110100011001010111001101110100";
String s2Binary = "01110011011000010110110101110000011011000110010101001010010000010101011001000001";
BigInteger b1 = new BigInteger(s1Binary, 2);
BigInteger b2 = new BigInteger(s2Binary, 2);
System.out.println(b1.and(b2).toString(2));
System.out.println(b1.or(b2).toString(2));
You can pad the shorter string with leading zeros.
turn 01110100 01100101 01110011 01110100
into 00000000 00000000 00000000 00000000 00000000 00000000 01110100 01100101 01110011 01110100
Related
This question already has answers here:
What is the idea behind ^= 32, that converts lowercase letters to upper and vice versa?
(10 answers)
Closed 3 years ago.
I've found this code for swapping case, but I'm a bit confused on how it works.
class Main {
private static String swapCase(String s) {
String r = "";
for (char c : s.toCharArray())
r += c ^= 32; // this line
return r;
}
public static void main(String[] args) {
System.out.println(swapCase("Hello"));
}
}
I understood that it loops over each character. But, I can't wrap my head around the line (especially the XOR operator)
r += c ^= 32;
I mean what's the significance of 32? How it swaps the case?
This is how ASCII was set-up.
Letter from a-z have the 6-th bit set to 1; while letters from A-Z have the 6-th bit set to 0.
32 = 100000 // the 6-th bit is set to 1
doing a XOR with an int will invert that 6-th bit.
You could do a little of debugging and see yourself:
for (char c : s.toCharArray()) {
System.out.println(Integer.toBinaryString((int) c));
c ^= 32; // this line
System.out.println(Integer.toBinaryString((int) c));
}
For ASCII encoding 32 is the difference between a lower-case letter and an uppercase letter. It's a power of two, its binary representation is a single 1-bit:
0010 0000.
By applying the XOR assignment operator, you change this bit in the character value. Effectively adding (if the bit is 0 in c) or subtracting (bit is 1 in c) 32.
This will work fine for letters A-Z and a-z but will most likely do nonsense for most other characters in the input.
Let see this table and you will understand why
a = 01100001 A = 01000001
b = 01100010 B = 01000010
c = 01100011 C = 01000011
d = 01100100 D = 01000100
e = 01100101 E = 01000101
f = 01100110 F = 01000110
g = 01100111 G = 01000111
h = 01101000 H = 01001000
i = 01101001 I = 01001001
j = 01101010 J = 01001010
k = 01101011 K = 01001011
l = 01101100 L = 01001100
m = 01101101 M = 01001101
n = 01101110 N = 01001110
o = 01101111 O = 01001111
p = 01110000 P = 01010000
q = 01110001 Q = 01010001
r = 01110010 R = 01010010
s = 01110011 S = 01010011
t = 01110100 T = 01010100
u = 01110101 U = 01010101
v = 01110110 V = 01010110
w = 01110111 W = 01010111
x = 01111000 X = 01011000
y = 01111001 Y = 01011001
z = 01111010 Z = 01011010
The only difference from the upper and lower version is the 5th bit (count from 0). That's why with a simple XOR mask, you can change the case back and forth.
I need to somehow concatenate a series of 8 integers into a single long in Java. The values of the integers are between 0-255. They have to be combined in this manner: Lets say we got this sample of integers (in binary):
00000000 00000000 00000000 11111111
00000000 00000000 00000000 11111101
00000000 00000000 00000000 11110111
00000000 00000000 00000000 10111111
00000000 00000000 00000000 11110011
00000000 00000000 00000000 10111111
00000000 00000000 00000000 01111111
00000000 00000000 00000000 00111111
The resulting float will have to be:
11111111 11111101 11110111 10111111 11110011 10111111 01111111 00111111
Is this somehow achievable in Java?
I have tried using bytes instead of integers but in Java, bytes (and probably every other data type) are signed, so I had to convert them to integers as I can't deal with negative numbers, as I ll need to use them as arguments in another function. I am obligated to try to find a solution this way.
Any help would be appreciated.
You can use a ByteBuffer:
byte[] a = new byte[8];
a[0] = (byte) 255;
a[1] = (byte) 253;
a[2] = (byte) 247;
a[3] = (byte) 191;
a[4] = (byte) 243;
a[5] = (byte) 191;
a[6] = (byte) 127;
a[7] = (byte) 63;
ByteBuffer buffer = ByteBuffer.wrap(a);
System.out.println(buffer.getLong());
// Result:
// 11111111 11111101 11110111 10111111 11110011 10111111 01111111 00111111
Another way to create a ByteBuffer:
ByteBuffer buffer = ByteBuffer.allocate(Byte.SIZE);
buffer.put(0, (byte) 255);
buffer.put(1, (byte) 253);
// ...
buffer.put(7, (byte) 63);
System.out.println(buffer.getLong());
Also, you can use the getLong(...) method implementation separately without creating a ByteBuffer instance:
long result = getLong(a[0], a[1], a[2], a[3], a[4], a[5], a[6], a[7]);
System.out.println(result);
// Result:
// 11111111 11111101 11110111 10111111 11110011 10111111 01111111 00111111
long getLong(byte b7, byte b6, byte b5, byte b4, byte b3, byte b2, byte b1, byte b0) {
return ((((long) b7 ) << 56) |
(((long) b6 & 0xff) << 48) |
(((long) b5 & 0xff) << 40) |
(((long) b4 & 0xff) << 32) |
(((long) b3 & 0xff) << 24) |
(((long) b2 & 0xff) << 16) |
(((long) b1 & 0xff) << 8) |
(((long) b0 & 0xff) ));
}
I would do something like the following:
long result = 0
int[] values = { 1, 2, 3, 4, 5, 6, 7, 8 }
for (int i = 0; i < values.length; i++)
result |= values[i] << i*8;
The |= is a OR and set operator, << is the left shift, and i*8 is the offset in the long.
Here are the building blocks to help you build your own answer:
1) Getting the binary representation of your integer as String:
Integer.toBinaryString(x)
2) Shifting bits pattern x, y bits to the left:
x << y
3) Taking 2 bit patterns x and y of equal length and performing the logical inclusive OR operation:
x | y
4) Getting the binary representation of your long as String:
Long.toBinaryString(x)
Below is a possible solution (with extra methods for displaying the output), based on defined requirements:
public class Integers {
public static void main(String[] args) {
Integers integers = new Integers();
long result = integers.toLong(255, 253, 247, 191, 243, 191, 127, 63);
System.out.println(integers.toBinaryStringWithPadding(result));
}
private long toLong(int... input) {
if (input.length != 8) {
throw new IllegalArgumentException();
}
long result = 0;
for (int i = 0; i < input.length - 1; i++) {
System.out.println(toBinaryStringWithPadding(input[i]) + "\n");
result |= input[i];
result <<= 8;
}
System.out.println(toBinaryStringWithPadding(input.length - 1) + "\n");
result |= input[input.length - 1];
return result;
}
private String toBinaryStringWithPadding(int value) {
String binaryString = Integer.toBinaryString(value);
int padding = 32 - binaryString.length();
StringBuilder tmp = new StringBuilder(32 + 3);
for (int i = 0; i < 32; i++) {
if (i < padding) {
tmp.append('0');
} else {
tmp.append(binaryString.charAt(i - padding));
}
if (i != 0 && (i + 1) % 8 == 0) {
tmp.append(' ');
}
}
return tmp.toString();
}
private String toBinaryStringWithPadding(long value) {
String binaryString = Long.toBinaryString(value);
int padding = 64 - binaryString.length();
StringBuilder tmp = new StringBuilder(64 + 7);
for (int i = 0; i < 64; i++) {
if (i < padding) {
tmp.append('0');
} else {
tmp.append(binaryString.charAt(i - padding));
}
if (i != 0 && (i + 1) % 8 == 0) {
tmp.append(' ');
}
}
return tmp.toString();
}
}
The problem is to reverse the bits of a 32 bit unsigned integer (since Java doesn't have unsigned integers we use long).
Here are two versions of my code. I have two concerns:
(1) why my 1st and 2nd solution don't return the same value (correct or not)
(2) where my 1st and 2nd solution went wrong in not getting the correct answer
//reverse(3) returns 0
public static long reverse(long a) {
long numBits = 32;
long finalResult = 0;
for(int i = 0; i < numBits; i++){
long ithBit = a & (1 << i);
finalResult = finalResult + ithBit * (1 << (numBits - i - 1));
}
return finalResult;
}
Second version:
//reverse(3) return 4294967296
public static long reverse(long a) {
long numBits = 32L;
long finalResult = 0L;
for(long i = 0L; i < numBits; i++){
long ithBit = a & (1L << i);
finalResult = finalResult + ithBit * (1L << (numBits - i - 1L));
}
return finalResult;
}
This code (the solution) returns the correct answer, however:
//reverse(3) returns 3221225472
public static long reverse(long A) {
long rev = 0;
for (int i = 0; i < 32; i++) {
rev <<= 1;
if ((A & (1 << i)) != 0)
rev |= 1;
}
return rev;
}
Thanks!
Let's have a look at your values as you iterate. For clarification, we'll have a look at the intermediate values, so we'll change code to:
int n = (1 << (numBits - i - 1));
long m = ithBit * n;
finalResult = finalResult + m;
Your starting value is 3:
a = 0000 0000 0000 0000 0000 0000 0000 0011
First loop iteration (i = 0):
ithBit = 00000000 00000000 00000000 00000001
n = 11111111 11111111 11111111 11111111 10000000 00000000 00000000 00000000
m = 11111111 11111111 11111111 11111111 10000000 00000000 00000000 00000000
finalResult = 11111111 11111111 11111111 11111111 10000000 00000000 00000000 00000000
Second loop iteration (i = 1):
ithBit = 00000000 00000000 00000000 00000010
n = 01000000 00000000 00000000 00000000
m = 10000000 00000000 00000000 00000000
finalResult = 00000000 00000000 00000000 00000000
As you can see, the first iterate sets n = 1 << 31, which is -2147483648. In your second version you do n = 1L << 31, which is 2147483648, and that's why your two versions give different results.
As you can also see, you definitely don't want to do the m = ithBit * n part.
Have a look at your number by printing them yourself, and you'll figure it out.
BTW, here's my version. If you have trouble understanding it, try printing the intermediate values to see what's going on.
public static long reverse4(long a) {
long rev = 0;
for (int i = 0; i < 32; i++, a >>= 1)
rev = (rev << 1) | (a & 1);
return rev;
}
since Java doesn't have unsigned integers we use long.
That's generally unecessary since all arithmetic operations except division and comparison result in identical bit patterns for unsigned and signed numbers in two's complement representation, which java uses. And for the latter two ops Integer.divideUnsigned(int, int) and Integer.compareUnsigned(int, int) are available.
The problem is to reverse the bits of a 32 bit unsigned integer
There's Integer.reverse(int)
Relevant docs, spending some time reading them is highly recommended.
Problem with your both examples is that the "i-th bit" isn't a 0 or 1 but rather masked off. In either case, the 31'th bit is 0x8000_0000. In the first case, this is an int, so it is negative, and when converted to a long it stays negative. In the second case it is already a long, so it stays positive. To fix it so it does what you intended, do:
ithBit = (a >>> i) & 1;
By the way, using long is silly; unsigned vs. signed makes no difference as long as you understand that there are two types of shifts in Java.
By the way, all three examples are terrible. If you are doing bit manipulation, you want speed, right? (Why else bother with bits?)
This is how to do it right (not mine, stolen from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits):
a = ((a >>> 1) & 0x55555555) | ((a & 0x55555555) << 1);
a = ((a >>> 2) & 0x33333333) | ((a & 0x33333333) << 2);
a = ((a >>> 4) & 0x0F0F0F0F) | ((a & 0x0F0F0F0F) << 4);
a = ((a >>> 8) & 0x00FF00FF) | ((a & 0x00FF00FF) << 8);
a = ( a >>> 16 ) | ( a << 16);
In both versions you have a logic problem here:
ithBit * (1 << (numBits - i - 1));
because the two numbers multiply to the same bit pattern of bit 31 (the 32nd) being set.
In version 1, the amount added is -2^31 if bit 0 is set because you're bit-shifting an int so the bit-shifted result is int which represents -2^31 as the high bit being set, or 2^31 for every other bit, which is possible due to the auto-cast to long of the result. You have two of each kind of bit (0 and non 0) so the result is zero.
Version 2 has the same problem, but without the negative int issue because you're bit shifting a long. Each bit that is 1 will add 2^31. The number 3 has 2 bits set, so your result is 2 * 2^31 (or 2^32) which is 4294967296.
To fix your logic, use version 2 but remove the multiply by ithBit.
Ok this is probably something really stupid, but I can't understand why this isn't working;
byte temp = (byte)0x80;
System.out.println(temp);
byte holder = (byte)(temp | 0x40);
System.out.println(holder);
Produces:
-128
-64
Shouldn't a bitwise or on:
10000000
01000000
Yield
11000000
or -192?
0x80 represent 128 and 0x40 represent 64. If you print 0x80 | 64 it will output 192.
When you cast to byte 128 becomes -128 as 128 is higher then Byte.MAX_VALUE which is 127.
So the expression you evaluate is -128 | 64, while you were probably expecting 128 | 64, and will result in your output, -64.
Try printing them out this way instead:
byte b1 = (byte)0x80;
String s1 = String.format("%8s", Integer.toBinaryString(b1 & 0xFF)).replace(' ', '0');
System.out.println(s1);
byte b2 = (byte)0x40;
String s2 = String.format("%8s", Integer.toBinaryString(b2 & 0xFF)).replace(' ', '0');
System.out.println(s2);
byte b3 = (byte)(b1 | b2);
String s3 = String.format("%8s", Integer.toBinaryString(b3 & 0xFF)).replace(' ', '0');
System.out.println(s3);
I need to generate 512 bit BigInts, but I'm not sure which of the two below is true:
512 bits means 512 digits of 1010101010...001010 which are then converted to the decimal it represents?
Or does it mean 512 digits of 0-9, so basicly a 512-digit number with digits ranging from 0-9? Something like 12414124124....54543=512 digits.
From sourcecode, they are stored in an int array
The magnitude of this BigInteger, in big-endian order: the zeroth element of this array is the most-significant int of the magnitude. The magnitude must be "minimal" in that the most-significant int (mag[0]) must be non-zero. This is necessary to ensure that there is exactly one representation for each BigInteger value. Note that this implies that the BigInteger zero has a zero-length mag array.
118
119 int[] mag;
120
121 // These "redundant fields" are initialized with recognizable nonsense
122 // values, and cached the first time they are needed (or never, if they
123 // aren't needed).
124
Conceptually, BigInteger converts an integer into arbitrary-length bit string, and then split the bit string by 4bytes. Then, each 4bytes result is assigned into each element in mag array:
BigInteger bi = new BigInteger("1234567890");
byte[] bytes = bi.toByteArray();
String rs = "";
for (byte b : bytes) {
String bs1 = Integer.toBinaryString(b & 0xff);
String bs2 = String.format("%8s", bs1).replace(' ', '0');
rs = rs + bs2 + " ";
}
System.out.println(bi.signum()); // 1
System.out.println(bi.bitLength()); // 31
System.out.println(rs); // 01001001 10010110 00000010 11010010
The final int signum is 1 (00000000 00000000 00000000 00000001).
The mag[0] in final int[] mag is 1234567890 (01001001 10010110 00000010 11010010). Yes, mag has one element only.
Let's represent more bigger integer:
BigInteger bi = new BigInteger("12345678901234567890");
byte[] bytes = bi.toByteArray();
String rs = "";
for (byte b : bytes) {
String bs1 = Integer.toBinaryString(b & 0xff);
String bs2 = String.format("%8s", bs1).replace(' ', '0');
rs = rs + bs2 + " ";
}
System.out.println(bi.signum()); // 1
System.out.println(bi.bitLength()); // 64
System.out.println(rs); // 00000000 10101011 01010100 10101001 10001100 11101011 00011111 00001010 11010010
The final int signum is 1 (00000000 00000000 00000000 00000001).
The mag[0] in final int[] mag is -1420514932 (10101011 01010100 10101001 10001100).
The mag[1] in final int[] mag is -350287150 (11101011 00011111 00001010 11010010).
When we instantiate an BigInteger instance with a negative integer:
BigInteger bi = new BigInteger("-1234567890");
byte[] bytes = bi.toByteArray();
String rs = "";
for (byte b : bytes) {
String bs1 = Integer.toBinaryString(b & 0xff);
String bs2 = String.format("%8s", bs1).replace(' ', '0');
rs = rs + bs2 + " ";
}
System.out.println(bi.signum()); // -1
System.out.println(bi.bitLength()); // 31
System.out.println(rs); // 10110110 01101001 11111101 00101110
The final int signum is -1 (11111111 11111111 11111111 11111111).
The mag[0] in final int[] mag is 1234567890 (01001001 10010110 00000010 11010010). Yes, mag stores number's magnitude.
When we call toByteArray(), BigInteger converts mag array's magnitude representation into 2's complement representation because signum is -1, meaning negative value. So, do not treat toByteArray as BigInteger's internal representation.
When we instantiate an BigInteger instance with zero:
BigInteger bi = new BigInteger("0");
byte[] bytes = bi.toByteArray();
String rs = "";
for (byte b : bytes) {
String bs1 = Integer.toBinaryString(b & 0xff);
String bs2 = String.format("%8s", bs1).replace(' ', '0');
rs = rs + bs2 + " ";
}
System.out.println(bi.signum()); // 0
System.out.println(bi.bitLength()); // 0
System.out.println(rs); // 00000000
The final int signum is 0 (00000000 00000000 00000000 00000000).
The final int[] mag has no element; zero-sized array. The magnitude must be "minimal" in that the most-significant int (mag[0]) must be non-zero. This is necessary to ensure that there is exactly one representation for each BigInteger value. Note that this implies that the BigInteger zero has a zero-length mag