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.
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 would like to know which one is the best way to work with binary numbers in java.
I need a way to create an array of binary numbers and do some calculations with them.
For example, I would like to X-or the values or multiply matrix of binary numbers.
Problem solved:
Thanks very much for all the info.
I think for my case I'm going to use the BitSet mentioned by #Jarrod Roberson
In Java edition 7, you can simply use binary numbers by declaring ints and preceding your numbers with 0b or 0B:
int x=0b101;
int y=0b110;
int z=x+y;
System.out.println(x + "+" + y + "=" + z);
//5+6=11
/*
* If you want to output in binary format, use Integer.toBinaryString()
*/
System.out.println(Integer.toBinaryString(x) + "+" + Integer.toBinaryString(y)
+ "=" + Integer.toBinaryString(z));
//101+110=1011
What you are probably looking for is the BitSet class.
This class implements a vector of bits that grows as needed. Each
component of the bit set has a boolean value. The bits of a BitSet are
indexed by nonnegative integers. Individual indexed bits can be
examined, set, or cleared. One BitSet may be used to modify the
contents of another BitSet through logical AND, logical inclusive OR,
and logical exclusive OR operations.
By default, all bits in the set initially have the value false.
Every bit set has a current size, which is the number of bits of space
currently in use by the bit set. Note that the size is related to the
implementation of a bit set, so it may change with implementation. The
length of a bit set relates to logical length of a bit set and is
defined independently of implementation.
Unless otherwise noted, passing a null parameter to any of the methods
in a BitSet will result in a NullPointerException.
There's a difference between the number itself and
it's representation in the language. For instance, "0xD" (radix 16), "13" (radix 10), "015" (radix 8) and "b1101" (radix 2) are four
different representations referring to the same number.
That said, you can use the "int" primitive data type in the Java language to represent any binary number (as well as any number in any radix), but only in Java 7 you are able to use a binary literal as you were previously able to use the octal (0) and hexa (0x) literals to represent those numbers, if I understood correctly your question.
You can store them as byte arrays, then access the bits individually. Then to XOR them you can merely XOR the bytes (it is a bitwise operation).
Of course it doesn't have to be a byte array (could be an array of int types or whatever you want), since everything is stored in binary in the end.
I've never seen a computer that uses anything but binary numbers.
The XOR operator in Java is ^. For example, 5 ^ 3 = 6. The default radix for most number-to-string conversions is 10, but there are several methods which allow you to specify another base, like 2:
System.out.println(Integer.toString(5 ^ 3, 2));
If you are using Java 7, you can use binary literals in your source code (in addition to the decimal, hexadecimal, and octal forms previously supported).
I have in C++:
typedef struct _msk {
char abc[4];
//some more variables
}
_msk mr;
if (some condition >= 70) {
mr.abc[0] |= 0xC0; //C0 in binary 11000000
mr.abc[1] |= 0x20; //20 in binary 100000
mr.abc[2] |= 0x44; //44 in binary 1000100
}
here OR operation is goin on after which the value will be stored.
So in memory is it like (0th)11000000(1st)100000(2nd)1000100 as these are in array? how many bits can be actually stored in [4](total 0+1+2+3+4).
In Java:
private BitSet abc = new BitSet(40);
if a updation or modification of bits are required we can utilise set or get methods provided by the bitset class.
In java if we need to carry out the OR operation we need to add the 0's in the suffix to have the same result. Which we can avoid in c++??
Thanks
So in memory is it like
(0th)11000000(1st)100000(2nd)1000100
as these are in array?
almost: (0th)11000000(1st)00100000(2nd)01000100
how many bits can be actually stored
in [4](total 0+1+2+3+4).
Not 0+...+4, but 0+...+3, 4 chars of size 8 bits = 32 bits (indices: 0, 1, 2, 3)
And you can still use the bitwise operators in Java - not entirely sure what you are asking regarding the Java code ??
Since you are using the |=, you are actually doing mr.abc[0] = mr.abc[0] | 0xC0;
So this means the result depends on the original value of mr.abc[0], which may or may not be 0.
Also there are 8 bits in a char(1 byte)..so with 4 elements in the array there are 32 bits total.
Java uses the exact same notations for all the bitwise operations. I am not sure where you are going with the BitSet.
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).
I have code that stores values in the range 0..255 in a Java byte to save space in large data collections (10^9 records spread over a couple hundred arrays).
Without additional measures on recovery, the larger values are interpreted as being negative (because the Java integer types use two's complement representation).
I got this helpful hint from starblue in response to a related question, and I'm wondering if this technique is safe to rely on:
int iOriginal = 128, iRestore;
byte bStore = (byte) iOriginal; // reading this value directly would yield -128
iRestore = 0xff & bStore;
Yes, it's safe, indeed it's the most effective way of converting a byte into an (effectively) unsigned integer.
The byte half of the and operation will be sign-extended to an int, i.e. whatever was in bit 7 will be expanded into bits 8-31.
Masking off the bottom eight bits (i.e. & 0xff) then gives you an int that has zero in every bit from 8 - 31, and must therefore be in the range 0 ... 255.
See a related answer I gave here.