In order to convert from int to IP String I am using approach in Going from 127.0.0.1 to 2130706433, and back again
private static final byte BYTE_MASK = (byte)0xff;
protected byte[] unpack(int bytes) {
return new byte[] {
(byte)((bytes >>> 24) & BYTE_MASK),
(byte)((bytes >>> 16) & BYTE_MASK),
(byte)((bytes >>> 8) & BYTE_MASK),
(byte)((bytes ) & BYTE_MASK)
};
}
But FindBugs in Eclipse generates bugs: INT_VACUOUS_BIT_OPERATION.
INT_VACUOUS_BIT_OPERATION: bit operations that don't do any meaningful work.
Why is that and how to fix it?
I suspect it's because you don't need the & BYTE_MASK if you're also casting to byte. I'm assuming that BYTE_MASK is 0xff... in which case it's basically pointless. Just casting will have the same effect.
From section 5.1.3 of the JLS:
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.
Related
Why isn't there any function in the standard library of Kotlin/Java for taking the absolute value of a Byte/byte variable? I'm I missing something?
Math.abs() is only defined for int, long, double and float.
For context: in the audio world you can run easily into byte arrays representing the amplitude. I'm interested in calculating the average of the absolute values of a byte array. For e.g see this listener related to Visualizer in Android.
I know I can cast it to an integer and take the absolute value of that, but I would still be interested why is this not predefined.
The operations in java.lang.Math are in line with all other arithmetic operations in Java. Integer operations always work in either, 64 bit long or 32 bit int.
As stated in JLS, §4.2.2. Integer Operations
If an integer operator other than a shift operator has at least one operand of type long, then the operation is carried out using 64-bit precision, and the result of the numerical operator is of type long. If the other operand is not long, it is first widened (§5.1.5) to type long by numeric promotion (§5.6).
Otherwise, the operation is carried out using 32-bit precision, and the result of the numerical operator is of type int. If either operand is not an int, it is first widened to type int by numeric promotion.
In other words, not even the following, equivalent to abs, would compile:
byte a = 42, absA = a < 0? -a: a;
as the numeric operation -a will promote a to int before negating.
It’s important that a cast of the result to byte would not be a lossless operation here. The byte datatype has a value range from -128 to +127, so if the value is -128, its absolute value +128 is outside the byte value range and a cast to byte would cause an overflow to -127.
Therefore, to have a correct and efficient calculation, you should do as always in Java when it comes to byte, short, or char calculations, calculate everything using int and only cast the final result back to your data type. When you want to calculate the average, you have to calculate the sum using int anyway (or even long if you have more than 16777215 array elements).
byte[] array // e.g. test case: = { 1, -1, -128, 127 };
int sum = 0;
for(byte b: array) sum += Math.abs(b);
int average = sum/array.length;
// if you really need a byte result
byte byteAverage = average == 128? 127: (byte)average;
I don’t know about Kotlin, but in Java, the automatic promotion to int also works if the operand is of type Byte, so you don’t need to “cast it to an integer” to call Math.abs(int). You only have to deal with the fact that the result will be an int, as with all arithmetic operations on byte, short, char, or their wrapper types.
In java byte is signed between -128 and 127, corresponding as (unsigned) int: 0xFF & b between 128 .. 255, and 0 .. 127.
Math.abs is irrelevant here as probably unsigned byte values are assumed.
int[] bytesToInt(byte[] bs) {
int[] is = new int[bs.length];
Arrays.fill(is, i -> bs[i] & 0xFF);
return is;
}
byte byteAbs(byte b) {
return b >= 0? b : b == -128? 127 : -b;
}
byteAbs - given for completeness - reduces the range to 7 bits, and has the artefact that -128 maps to 127, as there is no 128.
I have question regarding my code here:
public class Main
{
public static void main(String[] args) {
System.out.println("Hello World\n");
int x = 36;
byte b1 = ((byte) x) & ((byte) 0xff); // it seems it is the part after &, but I have 0xff cast to byte by using (byte)0xff, so not sure where exactly the error is coming from.
System.out.println(b1);
}
}
I am not sure exactly which part is causing the error of:
incompatible types: possible lossy conversion from int to byte
This is the error message output from the program:
You appear to be confused.
There is no point in your code. taking any number, calculating that & 0xFF, and then storing it in a byte, is always a noop - it does nothing.
You additionally get an error because & inherently always produces at least an int (it'll upcast anything smaller to match), so you're trying to assign an int to a byte.
What are you trying to accomplish?
"I want to have my byte be unsigned"!
No can do. Java doesn't have unsigned bytes. A java byte is signed. Period. It can hold a value between -128 and +127. For calculation purposes, -128 and 255 are identical (they are both the bit sequence 1111 1111 - in hex, 0xFF, and they act identically under all relevant arithmetic, though it does get tricky when converting them to another numeric type int).
"I just want to store 255"!
Then use int. This is where most & 0xFF you'll ever see in java code comes from: When you have a byte value which java inherently treats as signed, but you wish to treat it as unsigned and, therefore (given that in java bytes can't do that), you want to upcast it to an int, containing the unsigned representation. This is how to do that:
int x = y & 0xFF;
Where y is any byte.
You presumably saw this somewhere and are now trying to apply it, but assigning the result of y & 0xFF to a byte doesn't mean anything. You'd assign it to an int variable, or just use it as expression in a further calculation (y & 0xFF is an int - make sure you add the appropriate parentheses, & has perhaps unexpected precedence).
int x = 36;
byte b1 = ((byte) x) & ((byte) 0xff);
Every imaginable way of this actually working would mean that b1 is... still 36.
To compute x & y where the two operands are bytes, they must first be promoted to int values. There is no & between bytes. The result is therefore of type int
That is, what you wrote is effectively evaluated as if you'd written it as the following, making explicit what the language gives you implicitly:
byte b1 = ((int) (byte) x) & ((int) (byte) 0xff);
Just do the arithmetic and then cast the result to byte.
byte b1 = (byte)(x & 0xff);
Link to Java Language Specification
Edited to add, thanks to #rzwitserloot, that masking a byte value with 0xff is however pointless. If you need the assignment from an integer to a byte, just write the cast:
byte b1 = (byte)x;
I want to store unsigned long value in two 16bit register.For example if I have long value (-2,147,483,648 to 2,147,483,647) then I'm using formula like:
v[0] = myValue % 65536
v[1] = myValue / 65536
To get value from register
outVal = reg0 + (reg1 * 65536)
But how to do for unsigned long which value range is from 0 to 4,294,967,295?
As commenter harold pointed out already, your formula doesn't even work correctly for negative numbers.
You should do it bitwise instead of using math to avoid surprises (and speed things up in case the compiler didn't optimize it for you already).
Splitting:
v[0] = myValue & 0xFFFF
v[1] = myValue >> 16 // this implicitly cuts off the lower 16 bits
// by shifting them away into the nirvana
Joining:
outVal = reg0 | (reg1 << 16)
This now applies to both signed and unsigned (provided that all your variables have the same "sign type").
Legend, in case your language (which you didn't specify) uses different operators:
& is bitwise AND, | is bitwise OR, << and >> are bitwise shifting left/right (SHL/SHR), 0x marks a hexadecimal literal (you could use 65536 instead of 0xFFFF, but I think the hex literal makes it clearer where this magic number comes from).
I'm trying to simplify some code for decoding data in a file and I've written a test case to show the issue.
Given two bytes as 0xFe and 0xFF I want that to be read as 0xFFFE (65534),
the existing code does
headerBuffer.get() & 0xff + (headerBuffer.get() & 0xff) * 256
I thought, if I made buffer byte order little endian, I could get same result by reading as a short. But I do not get same result, why not ?
headerBuffer.getShort();
public void testReadingOfShort() {
ByteBuffer headerBuffer = ByteBuffer.allocate(2);
headerBuffer.order(ByteOrder.LITTLE_ENDIAN);
headerBuffer.put((byte) 0xFE);
headerBuffer.put((byte)0xFF);
headerBuffer.position(0);
int format = headerBuffer.get() & 0xff + (headerBuffer.get() & 0xff) * 256;
headerBuffer.position(0);
int formatNew = headerBuffer.getShort();
System.out.println("Format:"+format+"("+ Hex.asHex(format)+")"+":FormatNew:"
+formatNew+"("+Hex.asHex(formatNew)+")");
}
Outputs
Format:65534(0xfffe):FormatNew:-2(0xfffffffffffffffe)
You do get the same value. The problem happens when you assign the short to an int on this line:
int formatNew = headerBuffer.getShort();
When you do this, Java performs sign extension to ensure that the numeric value in the short gets converted to the same numeric value in the int. In your case, that is -2.
The representation of -2 as a short is 0xFFFE, while the int representation is 0xFFFFFFFE. In other words, the sign bit of the short is copied into the additional upper bits of int.
You can address this by not assigning the short to int. You also need to make sure that your Hex.asHex has a proper overload for short, otherwise the same conversion would happen when formatNew gets passed as an argument.
Alternatively, if you would like to treat the value of the short as unsigned, and assign it to an int, you can mask the result with 0xFFFF, like this:
int formatNew = headerBuffer.getShort() & 0xFFFF;
My hypothesis here is that in your Hex class you have a .asHex() method taking a short as an argument which does something like:
int value = (int) argument;
Tough luck. If you "upcast" from one integer type to another, the sign bit, if present, is carried. Which means that if you try and cast short 0xfffe to an int, you will NOT end up with 0x0000fffe but... 0xfffffffe. Hence your result.
If you wanted to cast it as an unsigned value you'd have to mask it, like so:
int value = (int) argument & 0xffff;
You can simply obtain the desired value as
int formatNew = headerBuffer.getShort() & 0xFFFF;
or, alternatively, if you use Java 8:
int formatNew = Short.toUnsignedInt(headerBuffer.getShort());
This will basically drop all bits from the int that are not part of a short. But it won't relieve your from the responsibility of carefully checking where you expect unsigned values, and how to handle the (naturally) signed values in the respective context.
i have written these following three functions for my project to work:
WORD shuffling(WORD x)
{
// WORD - 4 bytes - 32 bits
//given input - a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15- b0,b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12,b13,b14,b15
//output required - a0,b0,a1,b1,a2,b2,a3,b3,a4,b4,a5,b5,a6,b6,a7,b7 - a8,b8,a9,b9,a10,b10,a11,b11,a12,b12,a13,b13,a14,b14,a15,b15
x = (x & 0X0000FF00) << 8 | (x >> 8) & 0X0000FF00 | x & 0XFF0000FF;
x = (x & 0X00F000F0) << 4 | (x >> 4) & 0X00F000F0 | x & 0XF00FF00F;
x = (x & 0X0C0C0C0C) << 2 | (x >> 2) & 0X0C0C0C0C | x & 0XC3C3C3C3;
x = (x & 0X22222222) << 1 | (x >> 1) & 0X22222222 | x & 0X99999999;
return x;
}
WORD t_function(WORD n)
{
WORD t_result=0;
WORD64 var = 2*((n*n)& 0xFFFFFFFF)+n; // (n*n mod FFFFFFFF) becomes a 32-bit word
t_result = (WORD) ((var)& 0xFFFFFFFF);
return t_result;
}
WORD lfsr(WORD t_result)
{
WORD returnValue = t_result;
WORD flag = 0;
flag = returnValue & 0x80000000; // Checking if MSB is 1 or 0
// Left shift the input
returnValue = returnValue << 1;
// If MSB is 1 then XOR the reult with the primitive polynomial
if(flag > 0)
{
returnValue = returnValue ^ 0x4C11DB7;
}
return returnValue;
}
WORD - unsigned long
this code is in "c". Now i have to implement this in java. Everything is fine in compiling and running the code. But here i used unsigned long and in java i have used int Since i am operating on 32bits at a time. The problem is "when implementing in java whenever the result is going out of range of int the output is being deviated and it will not be the same output from the c code. Is there any solution for my problem to replace the unsigned long range values in java
Update – Java 8 can treat signed int & long as if unsigned
In Java, the primitive integer data types (byte, short, int, and long) are signed (positive or negative).
As of Java 8 both int and long can be treated explicitly as if they are unsigned. Officially a feature now, but kind of a hack nonetheless. Some may find it useful in certain limited circumstances. See the Java Tutorial.
int: By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -2³¹ and a maximum value of 2³¹-1. In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 2³²-1. Use the Integer class to use int data type as an unsigned integer. See the section The Number Classes for more information. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.
long: The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -2⁶³ and a maximum value of 2⁶³-1. In Java SE 8 and later, you can use the long data type to represent an unsigned 64-bit long, which has a minimum value of 0 and a maximum value of 2⁶⁴-1. The unsigned long has a minimum value of 0 and maximum value of 2⁶⁴-1. Use this data type when you need a range of values wider than those provided by int. The Long class also contains methods like compareUnsigned, divideUnsigned etc to support arithmetic operations for unsigned long.
I am not necessarily recommending this approach. I’m merely making you aware of the option.
Short answer, there's no unsigned data type in java. long in C is 32-bit on 32-bit systems, but java's long is 64-bit, so you can use that for replacement (at least it would solve the overflow problem). If you need even wider integers, use BigInteger class.
Look over Java's Primitive Data Types. If you need something bigger than a long, try a BigInteger.