I want to do an "AND" operation between a and b (both decimal). the value of b is determined inside the code. As a result, if I write sth like:
String g= Integer.toHexString(b);
int k=a & g;
I get error, because it should be sth like:
int k=a & 0xFF;
somehow 0x should be before the hex value, and at the same time it can't be of type String. I did not find any example in Internet for the cases that the second operand can be a variable. Should I write manually a for loop to apply the AND operation bit by bit, or there is a straight forward solution for it?
I appreciate your help.
If b is already an integer, your code should just be:
int k = a & b;
A number is a number is a number. The human representations of 0xFF vs 255 makes no difference at all to the & operator. There is no such thing as a "Hex Integer" vs a "Decimal Integer" to the computer, it's just a value. The different ways of writing it are on the human end.
Just do this:
int k = a & b;
There's no need to convert an int to a hexadecimal before applying the & operator. In fact, that is an error, because the value returned by toHexString() is a String, and the & operator works for integers only.
When you write the hex literal 0xFF in your java code, it's the same as writing integer literal 255.
Hence there's no point converting your integer to string, doing a & b is sufficient. The hex notation is just how you specify your literal
Related
Problem
I wanted to perform bit operation with Java and was expecting the same behavior that happens with C or C++. However it is not working as intended.
In C or C++
printf("%d", 0 > 0xFFFFFFFF);
this would return 0 (which is false)
However in Java
System.out.println(0 > 0xFFFFFFFF);
returns true
What I understand
I know how 2's complement works. The below is that I am guessing what is happening internally with those two languages.
C++ or C just translates 0xFFFFFFFF to 0xFFFFFFFF itself, so value 0 is smaller than 0xFFFFFFFF thus resulting false.
Java translates 0xFFFFFFFF with 2's complement as -1, so value 0 is bigger than -1 thus resulting true.
Question
Is there any possible way that Java can work just like C++ or C did? I would like Java's hex values to be recognized as hex values instead of converting them into signed int values?
In Java the literal 0xFFFFFFFF represents the int whose value is -1. In Java int is a signed type.
In C / C++ 0xFFFFFFFF will typically be either a long or an unsigned long. In the former case, it represents -1. In the latter case it represents 2^32 - 1 ... a very large positive integer.
Is there any possible way that Java can work just like C++ or C did?
No.
I would like Java's hex values to be recognized as hex values instead of converting them into signed int values?
Well the problem is that Java int is signed. And you can't change that.
However, there are methods in the Integer class that will treat an int value as if it was unsigned; e.g. Integer.compareUnsigned, divideUnsigned and parseUnsignedInt. See the javadocs for more details.
I read SHA-256 from a book, but the book doesn't explain what it is for? The book explained how to create it in Java. However, I failed to understand what Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1)) is for. Can someone explain it to me in detail?
Integer.toString((byteData[i] & 0xff) + 0x100, 16).substring(1))
is one way of converting a byte value to a string that's exacly two character wide, showing the byte's hexadecimal value. Having a look at String's Javadoc page will help.
The combination of 0x100 and substring(1) ensures that byte values < than 16 decimal (that is, 0 to F in hex) are also represented as two characters.
By the way:
String.format("%02x",byteData[i])
does exactly the same, and might be considered more readable, especially by people who are used to C printf style format strings.
Lastly, why (byteData[i] & 0xff) ? See here for a detailed explanation:
It works because Java will perform a widening conversion to int, using
sign extension, so instead of a negative byte you will have a negative
int. Masking with 0xff will leave only the lower 8 bits, thus making
the number positive again (and what you initially intended).
SHA-256 is called a hash algorithm, and its purpose is simple: it takes any data and generates a unique series of bytes to represent it. There is no way to reverse this process, and there are no known instances of a SHA-256 hash being not unique.
The purpose of the line of code in question is to generate one character of the final SHA-256 output. Java gives you the has in raw data (a byte array) and we typically convert it to hexadecimal to represent it as a string. That line of code is pretty complex, so I'll go over what each part of it does separately.
sb.append(); is taking the imput and adding it to the result stored in a StringBuilder.
Integer.toString(); Takes a number and represents it as a literal string
byteData[i] & 0xff Selects the current byte of hash data and uses the bitwise and operation using 0xff (so for each bit in the byte, if the corresponding bit in 0xff is the same, the output is a 1, if not the output is a 0.
string.substring(1); Outputs the string starting after the first character.
1) Why is the following assignment not allowed:
byte b = 0b11111111; // 8 bits or 1 byte
but this assignment is allowed:
int i = 0b11111111111111111111111111111111; //32 bits or 4 bytes
Both types are signed, and I would expect b and i were -1.
2) Why doesn't the Integer MIN_VALUE have a sign?
public static final int MIN_VALUE = 0x80000000;
but the Byte MIN_VALUE does have a sign?
public static final byte MIN_VALUE = -128;
Question 1)
This is because 0b11111111 is an int literal, whose value is 255. This value doesn't fit into a byte. See http://docs.oracle.com/javase/7/docs/technotes/guides/language/binary-literals.html for more details on this.
Question 2)
When we write binary or hexadecimal literals, we never put a sign. The literal 0x80000000 is actually a negative value, even though we don't write it as such.
There's no really good reason why the makers of the JDK chose to use a decimal literal for -128 but a hexadecimal literal for 0x80000000; except that in each case, it's probably a whole lot clearer that way what is intended.
All integer literals have type int (unless suffixed by an L or l). Thus, in the first case, you're storing an int into a byte. A narrowing conversion like this is not allowed without a cast, except that if the right side is a constant, it's allowed if the value is in range, which is -128 to 127. 0b11111111 is 255, though, which is not in range.
As for why int i = 0b11111111111111111111111111111111 is allowed: it's pretty much "because the JLS says so". In fact, that specific example appears in JLS 3.10.1. There's a rule that decimal literals of type int cannot exceed 214743647 (except in the specific case -2147483648), but there's no rule about binary literals except that they have to fit into 32 bits.
As I mentioned in a comment, the second question is really a question about the style preference of the programmers who wrote the code, and it's impossible to answer.
I'm working on an assignment for school and I'm getting strange output. So, I figured I should start checking some of my more basic methods before I get to the fancier ones. The question I have is this:
would the method
public static short get16(byte a, byte b){
return (short)(a*Math.pow(2,8)+b)
}
return a short where the first 8 bits are byte a and the last 8 bits are byte b?
I don't see why it wouldn't, since multiplying by 2^8 would be the same as left shifting 8 bits to the left. And adding the second byte would make up for the 8 0's achieved by multiplying by 2^8. Is this correct?
I wouldn't recommend using Math.pow to compute 256. pow is notoriously hard to implement correctly; some extant implementations don't even get the exact cases right!
Also, bytes in Java are signed, so you probably want to say (a&255) and (b&255) rather than just a and b. Sign extension will ruin everything for you.
Some things you should know:
"Math.pow" is a floating-point function. Don't do integer calculation by calling floating-point functions and then rounding the result.
Java virtual machine is internally a 32-bit system. All "byte" and "short" mathematical expressions are internally evaluated as "int". Even an addition of two bytes goes internallly like this: 1) convert the bytes to ints, 2) add the ints, 3) convert the lower 8 bits to byte.
The correct way is:
return (short) ((a << 8) + (b & 255));
or
return (short) ((a << 8) | (b & 255));
When "byte" is converted to "int", the sign bit gets copied into the new bits. For example 0b01010101 becomes 0b00000000_00000000_00000000_01010101, because the first bit was 0, but 0b10101010 becomes 0b11111111_11111111_11111111_10101010.
Example code:
int a = 255;
byte b = (byte) a;
int c = b & 0xff; // Here be dragons
System.out.println(a);
System.out.println(b);
System.out.println(c);
So we start with an integer value of 255, convert it to a byte (becoming -1) and then converting it back to an int by using a magic formula. The expected output is:
255
-1
255
I'm wondering if this a & 0xff is the most elegant way to to this conversion. checkstyle for example complains about using a magic number at this place and it's not a good idea to ignore this value for this check because in other places 255 may really be a magic number which should be avoided. And it's quite annoying to define a constant for stuff like this on my own. So I wonder if there is a standard method in JRE which does this conversion instead? Or maybe an already defined constant with the highest unsigned byte value (similar to Byte.MAX_VALUE which is the highest signed value)
So to keep the question short: How can I convert a byte to an int without using a magic number?
Ok, so far the following possibilities were mentioned:
Keep using & 0xff and ignore the magic number 255 in checkstyle. Disadvantage: Other places which may use this number in some other scope (not bit operations) are not checked then, too. Advantage: Short and easy to read.
Define my own constant for it and then use code like & SomeConsts.MAX_UNSIGNED_BYTE_VALUE. Disadvantage: If I need it in different classes then I have to define my own constant class just for this darn constant. Advantage: No magic numbers here.
Do some clever math like b & ((1 << Byte.SIZE) - 1). The compiler output is most likely the same because it gets optimized to a constant value. Disadvantage: Pretty much code, difficult to read. Advantage: As long as 1 is not defined as magic number (checkstyle ignores it by default) we have no magic number here and we don't need to define custom constants. And when bytes are redefined to be 16 bit some day (Just kidding) then it still works because then Byte.SIZE will be 16 and not 8.
Are there more ideas? Maybe some other clever bit-wise operation which is shorter then the one above and only uses numbers like 0 and 1?
This is the standard way to do that transformation. If you want to get rid of the checkstyle complaints, try defining a constant, it could help:
public final static int MASK = 0xff;
BTW - keep in mind, that it is still a custom conversion. byte is a signed datatype so a byte can never hold the value 255. A byte can store the bit pattern 1111 1111 but this represents the integer value -1.
So in fact you're doing bit operations - and bit operations always require some magic numbers.
BTW-2 : Yes, there is a Byte.MAX_VALUE constant but this is - because byte is signed - defined as 27-1 (= 127). So it won't help in your case. You need a byte constant for -1.
Ignore checkstyle. 0xFF is not a magic number. If you define a constant for it, the constant is a magic constant, which is much less understandable than 0xFF itself. Every programmer educated in the recent centuries should be more familiar with 0xFF than with his girlfriend, if any.
should we write code like this?
for(int i = Math.ZERO; ... )
Guava to the rescue.
com.google.common.primitives.UnsignedBytes.toInt
Java 8 provides Byte.toUnsignedInt and Byte.toUnsignedLong (probably for really big bytes) methods:
byte b = (byte)255;
int c = Byte.toUnsignedInt(b); // 255
long asLong = Byte.toUnsignedLong(b); // 255
I wrote a method for this like
public static int unsigned(byte x) {
return int (x & 0xFF);
}
which is overloaded for short and int parameters, too (where int gets extended to long).
Instead of 0xFF you could use Byte.MAX_VALUE+Byte.MAX_VALUE+1 to keep FindBug shut, but I'd consider it to be an obfuscation. And it's too easy to get it wrong (s. previous versions).