How to check if bit is set in Hex-String? - java

shifters...
I've to do something, that twist my mind.
I'm getting a hex value as String (for example: "AFFE") and have to decide, if bit 5 of Byte one is set.
public boolean isBitSet(String hexValue) {
//enter your code here
return "no idea".equals("no idea")
}
Any hints?
Regards,
Boskop

The simplest way is to convert String to int, and use bit arithmetic:
public boolean isBitSet(String hexValue, int bitNumber) {
int val = Integer.valueOf(hexValue, 16);
return (val & (1 << bitNumber)) != 0;
} ^ ^--- int value with only the target bit set to one
|--------- bit-wise "AND"

Assuming that byte one is represented by the last two digits, and the size of the string fixed to 4 characters, then the answer may be:
return (int)hexValue[2] & 1 == 1;
As you an see, you don't need to convert the whole string to binary to evaluate the 5th bit, it is indeed the LSB of the 3rd character.
Now, if the size of the hex string is variable, then you will need something like:
return (int)hexValue[hexValue.Length-2] & 1 == 1;
But as the string can have a length smaller than 2, it would be safer:
return hexValue.Length < 2 ? 0 : (int)hexValue[hexValue.Length-2] & 1 == 1;
The correct answer may vary depending on what you consider to be byte 1 and bit 5.

How about this?
int x = Integer.parseInt(hexValue);
String binaryValue = Integer.toBinaryString(x);
Then you can examine the String to check the particular bits you care about.

Use the BigInteger and it's testBit built-in function
static public boolean getBit(String hex, int bit) {
BigInteger bigInteger = new BigInteger(hex, 16);
return bigInteger.testBit(bit);
}

Related

I want to count set bits of binary number of any given number. But the range of given number can vary to 10^200

I want to count set bits of binary number of any given number.
But the range of given number can vary to 10^200.
I tried using BigInteger and converted bigInteger to binary string using num.toString(2);
But maximum range of string is 2^31.
Any idea what else I can use here.
A BigInteger can be converted to a byte[] using BigInteger.toByteArray(). You can then iterate over the byte[] and count the set bits in each byte using code found here:
https://www.geeksforgeeks.org/count-set-bits-in-an-integer/
Note that int can be replaced with byte in that example.
There's bitCount() method you can use for that:
// So, we create a big number
BigInteger num = new BigInteger("10");
num = num.pow(200);
System.out.println(num.bitCount());
Just for fun, you can test that it gives you the correct number:
String binaryNum = num.toString(2);
System.out.println(binaryNum);
System.out.println(binaryNum.chars().filter(c -> c == '1').count());
The maximum range of a String in Java is 2^31 - 1 is true but it's not about the Maximum value of a number it can hold, it is about the Number of characters it can contain.
That said, you don't need BigInteger to find the number of set bits in a number (Even for a large number), just remember the way to find Binary representation of a number.
Ex:
2|12|0
2| 6|0
2| 3|1
2| 1|-
So from the above, we know that the binary representation of 12 is 1100.
We can easily calculate the number of set bits if know the binary representation of a number.
Coming to the problem, you know that you can't handle that big into a number, so use a string to store the number and perform the above method.
To divide a number that is stored in a string start dividing the part of the number from the start,i.e., the most significant digit of the decimal number.
Check whether it propagates a carry to the right, you can do this by a simple &1 which tells about the LSB of those digits.
Finally, count the number of set bits with b.
public class Expelliarmus{
public static void main(String[] args) {
String a = "9000000000000000000000000000000000000000000000000000000000000000000000000000000000000";//88 zeroes, you can test it for other numbers too
System.out.println(fn(a,0L));
}
static long fn(String a, long b){ // Don't ask why I used long here
if(a.length()==0) return b;
if(a.length()==1 && a.charAt(0)=='1') return ++b;
int n = Integer.parseInt(a.charAt(a.length()-1)+"");
if((n&1)==1) ++b;
a = divideMe(a);
return fn(a,b);
}
static String divideMe(String a){
int val = 0;
String bb = "";
for(int i=0;i<a.length();i++){
int dup = 0;
val = val*10 + Integer.parseInt(a.charAt(i)+"");
if((val&1)==1) dup = 1;
val = val/2;
bb = bb + String.valueOf(val);
val = dup;
}
if(bb.charAt(0)=='0') return bb.substring(1);
return bb;
}
}

Hash a String into fixed bit hash value

I want to hash a word into fixed bit hash value say 64 bit,32 bit (binary).
I used the following code
long murmur_hash= MurmurHash.hash64(word);
Then murmur_hash value is converted into binary by the following function
public static String intToBinary (int n, int numOfBits) {
String binary = "";
for(int i = 0; i < numOfBits; ++i) {
n/=2;
if(n%2 == 0)
{
binary="0"+binary;
}
else
binary="1"+binary;
}
return binary;
}
Is there any direct hash method to convert into binary?
Just use this
Integer.toBinaryString(int i)
If you want to convert into a fixed binary string, that is, always get a 64-character long string with zero padding, then you have a couple of options. If you have Apache's StringUtils, you can use:
StringUtils.leftPad( Long.toBinaryString(murmurHash), Long.SIZE, "0" );
If you don't, you can write a padding method yourself:
public static String paddedBinaryFromLong( long val ) {
StringBuilder sb = new StringBuilder( Long.toBinaryString(val));
char[] zeros = new char[Long.SIZE - sb.length()];
Arrays.fill(zeros, '0');
sb.insert(0, zeros);
return sb.toString();
}
This method starts by using the Long.toBinaryString(long) method, which conveniently does the bit conversion for you. The only thing it doesn't do is pad on the left if the value is shorter than 64 characters.
The next step is to create an array of 0 characters with the missing zeros needed to pad to the left.
Finally, we insert that array of zeros at the beginning of our StringBuilder, and we have a 64-character, zero-padded bit string.
Note: there is a difference between using Long.toBinaryString(long) and Long.toString(long,radix). The difference is in negative numbers. In the first, you'll get the full, two's complement value of the number. In the second, you'll get the number with a minus sign:
System.out.println(Long.toString(-15L,2));
result:
-1111
System.out.println(Long.toBinaryString(-15L));
result:
1111111111111111111111111111111111111111111111111111111111110001
Another other way is using
Integer.toString(i, radix)
you can get string representation of the first argument i in the radix ( Binary - 2, Octal - 8, Decimal - 10, Hex - 16) specified by the second argument.

Compressing a string in java with limited characters allowed

One of my friends got this interview question. In addition, he was told he could assume the characters were letters a to z (upper or lower case). I wrote the following, but I can't figure out how to use the assumption about the limited characters (a to z) the string contains. Am I using this assumption without realizing it or can I make use of it?
public static String compress(String str){
int count = 1;
char c = str.charAt(0);
StringBuffer result = new StringBuffer();
for (int i = 1; i < str.length();i++){
if (str.charAt(i) == c){
count++;
}
else{
String to_add = c + String.valueOf(count);
result.append(to_add);
count = 1;
c = str.charAt(i);
}
}
// last character
String to_add = c + String.valueOf(count);
result.append(to_add);
String result_str = result.toString();
// Check whether the compressed string is
// actually smaller than the original one
if (result_str.length() < str.length()){
return result_str;
}
else{
return str;
}
}
Assign each character to a number, eg a = 1, z = 26. So, to represent these 26 characters you need at least 5 bits.
You can now use 2 bytes (16 bits) to store a triplet of characters. This requires 1/3 less bytes than the initial one byte per character (if ascii). To store a triplet of characters read bits from your bytes (for example left to right).
First five bits of the first byte will represent the first character
The next three bits of the first byte, concatenated with the first two bits of the second byte represent the second
the next five bits from second byte represent the third character
there is one bit left (ignore it)
*To slightly improve in compression size, if your String's length % 3 = 1, then for the last character of your String you can use one byte only as you don't have another triplet.
**You can get if a specific bit is set on a byte using the algorithm from this post, which is:
public byte getBit(byte b, int position)
{
return (b >> position) & 1;
}
***You can set a bit to a byte using the algorithms from this post, which are:
to set a bit (set it to one)
b = b | (1 << position);
To unset a bit (set it to zero):
b = b & ~(1 << position);
****Using maths (least common multiple of 5 and 8), you could even slightly improve in compression size if you used 5 bytes = 40bits, which can represent 8 characters (8x5=40).
Then you would store octets of characters and there are no bits to ignore now. For the last characters of your String, depending on (string size % 8), you could again use less bytes.
*****Using the last 5-byte approach you get 3/8 less size, which is better than 1/3 of the 3-byte approach.
'a' to 'Z' is 2*26=52 distinct characters, and it fits in 6-bits (2^6=64). You could just pack the code-points into sextets.
OTOH, RLE (what you have coded) works only for repetitions. If you have input like abcde it would turn into 1a1b1c1d1e or something alike, which is highly inefficient and you can hardly call it compression.

Java: Changing a Binary number like 1010 and reversing the bits. 1010 = 0101. 0's to 1's and 1's to 0's

I have been searching around the web and seems like I can never seem to find the answer to this question. How do you change the bits in a binary number?
Example: say I got 1010 and I want to change the numbers 0's to 1's and 1's to 0's.
Right now, I have the binary number in a integer.
I'm completely stumped, if anyone could help me thank you.
Sorry if people are confused from my question . What i want to do is change the numbers 0's to 1's and 1's to 0's .
If you want to flip all the bits you can do
int i = 0b1010;
or in Java 6
int i = Integer.parseInt("1010", 2);
int i2 = ~i; // toggle 0 and 1's.
int i3 = i ^ 0xFF; // toggle the lower 8 bit only.
or you can try
public static void main(String... args) {
System.out.println(toggleBits("1010"));
System.out.println(toggleBits("00001010"));
System.out.println(toggleBits("1100001010"));
}
private static String toggleBits(String s) {
long i = Long.parseLong(s, 2);
long i2 = i ^ ((1L << s.length()) - 1);
String s2 = Long.toBinaryString(i2);
while (s2.length() < s.length()) s2 = '0' + s2;
return s2;
}
Are you not just looking for this method on Integer: http://docs.oracle.com/javase/6/docs/api/java/lang/Integer.html#reverse(int)?
This should do the trick.
if you are trying to do bit reversing operation similar to string reverse operation, then I think Java has a method named "reverse()" (or similar) which will work for you, I guess. You can also try the answer by #Dozz.
A quick demonstration for what was discussed and suggested in the comments would be:
int i = 42;
int j = i ^ 0xFF;
System.out.println(Integer.toBinaryString(i));
System.out.println(Integer.toBinaryString(j));
See more about XOR here.

Convert number to binary string with full padding?

I have a long variable in java and am converting it to a binary string, like
long var = 24;
Long.toBinaryString(val);
Now this prints only 7 bits, but I need to display all the 64 bits, i.e. all the leading zeros also, how can I achieve this?
The reason is I need to iterate through each bit and perform an operation according to the status, is there a better way to do it?
If you want to iterate through the bits, you might be better off testing each bit without converting it to a string:
if ((val & (1L << bitPosition)) != 0)
// etc
But, if you truly want a binary string, this is the easiest way to left-pad it with zeros:
string padding = "0000000000000000000000000000000000000000000000000000000000000000";
string result = padding + Long.toBinaryString(val);
result = result.substring(result.length() - 64, result.length()); // take the right-most 64 digits
You can use binary operators to access the individual bits of an long. The following code prints the individual bits of "i" as "true" or "false".
long i = 1024;
for(int n = 63; n >= 0; n--)
System.out.println(n + ": " + ((i & (1L << n)) != 0));
Not sure, but I think it should go like this:
int i=0, thisbit;
mask = 1;
while (i++ < 64)
{
thisbit = var & mask;
// check thisbit here...
//
var = var >>> 1;
mask*=2;
}
I would add little modification on #Robert's answer. Instead of declaring padding variable here, use Long.numberOfLeadingZeros(long).
Actually internally it make use of shift operators only.
Yes, see http://java.sun.com/docs/books/tutorial/java/nutsandbolts/op3.html for information on bitwise operations.
Otherwise use the Formatter: http://java.sun.com/j2se/1.5.0/docs/api/java/util/Formatter.html
This will work;
String s = Long.toBinaryString(val);
while (s.length() < 64)
{
s = "0" + s;
}
If you want to do this with a StringBuffer, so;
StringBuffer s = new StringBuffer(Long.toBinaryString(val));
while (s.length() < 64)
{
s.insert(0, "0");
}
String str = s.toString();

Categories