Reading bit inside 2 byte - java

int id = ((reply[0] & 0x3));
id = (id<<7) | (reply[1] & 0x7F);
Suppose I have a reply array storing 2 byte reply[0] and reply[1].
I wanna read the last two bits in the first byte and all the bits in the second byte, then adding them together
why the code above is going to work, can anyone explain?

This code is not doing what you described: instead of taking the second byte in its entirety, it cuts out its last seven bits (the & 0x7F part; 0x7F is binary 01111111), and concatenates them to the two last two bits of the first number (the << 7 part).

Convert to binary and you will get your answer.
binary of 3 is 11. if you use logical & with 11 you will end up only with the last two bits. That's the answer to your first part.
For the second part, I don't think it will do what you intended it too. You can use logical AND (for carry) and logical XOR to add individual bits.
Try to figure it out ^_^

Related

Difficult formula

I am new to bytes and bits and I'm also not very good in maths either. I kind of understand the bitwise operators, but I don't know how to solve math equations/formulas with 2 variables. I'm not sure this is the proper place to ask this but anyway.
I have an formula like this:
(Adr_MSB & 0x3F) << (8 + Adr_LSB)
Now what I want is that I would get an integer (for example 33) and the code would transform it into Adr_MSB and Adr_LSB (which are bytes).
It should work up to 128 (ok I guess it will be 127).
I know that this question might sound dumb or something, but I just don't know enough maths to solve this.
Thanks for all help.
EDIT: By experimenting I figured out, that Adr_MSB is a multiplier (e.g. if it's 10 the result is 10 times biger than if it's 1).
From what I understand
the (Adr_MSB & 0x3F) part of the takes the last six bits of the Adr_MSB and returns corresponding integer.
Eg: 125 (1111101) will return 61 (111101)
Note: This step is removing all bits other than last 6 bits, these bits are lost. Hence Lossless inverse function is not possible.
The (8 + Adr_LSB) just adds 8 to Adr_LSB.
<< is a bit wise Left Shift Operator.
Eg. 61 << 3 = 488 . Since 61 is 111101, adding three zeros to the right (Left Shifting three times) will give 111101000 which is 488.
Effective inverse of the expression (Adr_MSB & 0x3F) << (8 + Adr_LSB) to be applied to given number x
Take first six bits from x and convert it to int. This will be Adr_MSB.
Count the rest of the bits. Subtract 8 from this count and it will be Adr_LSB.
Does the following represent what you are looking for?
((Adr_MSB & 0x3F) << 8) | Adr_LSB
Would this work?
int x = 33;
byte Adr_MSB = (byte)x;
byte Adr_LSB = (byte)24;
System.out.println((Adr_MSB & 0x3F) << (8 + Adr_LSB));
Adr_LSB can also be -8.
Since you do bitwise AND on Adr_MSB and 111111, you have only six consecutive bits available to represent the number, so not all integers can be represented just by shifting those 6 bits. This solution works for x up to , so... you can argue that is not a good solution, but it is a start.

Java generate code byte 256*256 & 0xff

I need to generate a 3-bytes code (like A502F1). I am given a criteria:
1st byte is (serialCodeNumber / (256*256) ) & 0xFF
2nd is (serialCodeNumber / 256) & 0xFF
3th is (serialCodeNumber) & 0xFF
serialCodeNumber is a sequence 1-0xFFF
What does that mean!?
I would generate it like this:
String codeNum = new BigInteger(256, random).toString(16).toUpperCase().substring(0, 6);
But what is the right way of doing it as the requirement says?
I'm not quite sure what is meant by the serialCodeNumber, since if it is later on divided by 65025 it has to be a considerably larger number than 0xFFF (which is 4095) for it to make any reasonable sense.
But let's take a look at the conditions, they would all make sense once you are accustomed to the bitwise AND operator. A good read is available here on how it works but the meat of the matter from that question in my opinion is this sentence by Markus Jarderot:
The result is the bits that are turned on in both numbers.
Since in your conditions you have & 0xFF and 0xFF is 255, or in binary it's 11111111 the first eight bits that are all turned on. This is a neat trick to just retrieve only the first 8 bits of any number. And as we all know 8 bits make up a byte. (Are you starting to see where this all is coming together now?)
As for the conditions before the & 0xFF, some might recognize them as bit shift operations hidden behind divisions.
(serialCodeNumber / (256*256)) is equivalent to (serialCodeNumber >> 16)
and
(serialCodeNumber / 256) is equivalent to (serialCodeNumber >> 8)
But that is not that important in this case.
So the first condition takes the serialCodeNumber divides it by 65025 (256*256) and then looks at the 8 right most bits and ignores any other, from those 8 bits it constructs a byte.
In Java you can pretty much just write the condition as it is:
byte myFirstByte = (byte) ((serialCodeNumber / (256*256)) & 0xFF);
The other conditions aren't much different:
byte mySecondByte = (byte) ((serialCodeNumber / (256)) & 0xFF);
and
byte myThirdByte = (byte) ((serialCodeNumber) & 0xFF);
Once you have all three of your bytes, I'm assuming you need to convert them to a hex String. So I'll add them into a byte array.
byte[] myArray = {myFirstByte,mySecondByte,myThirdByte};
And borrow some method on how to convert byte arrays to HEX strings from this question.
String codeNum = bytesToHex(myArray);
And the result will look something like this:
F03DD7
EDIT:
Since you have to generate a serial number that has to be up to 6 bytes in value, I'd recommend using a long number.
A 6 byte number will be anywhere from 1 to 281474976710655, so you probably need to generate one randomly.
First instantiate a Random object which you will be able to poll numbers from:
Random random = new Random();
Once you have that, poll a long from it for the range 1 to 281474976710655.
For this you can borrow KennyTM's answer from this question.
So you can then generate the number like so:
long serialCodeNumber = nextLong(random, 281474976710655L)+1L;
We add the +1L at the end since we want it to include the last number as well as start from 1 instead of 0.
If you ever need to show a HEX string of the serialCodeNumber you can then just call:
String serialHex = Long.toHexString(serialCodeNumber);
But make sure to add any additional "0"s at the left side based on the length of the string so that it is 6-bytes = 12 characters long.

Can we read 4th byte from hexadecimal value?

Actually I am not so clear about it so I put a question here, and I am also new to bit calculation. My scenario is like this, I get some hexadecimal value from CAN (A hardware device) , for one perticular value I have to read 4th byte , in this 4th byte the value of bit 5 and 6 decides the output to be written, I mean if 5 & 6 th bit is 00= off , 01= on like this. So my question is , how can we read 4th or any particular byte and in byte particular bits from a hexadecimal. If possible please give me some guidance or examples or any tutorial sites. I googled a lot but no use . Please help me in this. and I want this to be done in java.
Assume that the value is 32 bit.
for example assume the input is 0x4FAEBCDB
I am assuming you want to extract the 4 byte which is DB.
Doing the AND operation with 0x000000FF will extract just the 4th byte.
That is
0x4FAEBCDB & 0x000000FF = 0xDB
Similarly you can extract each individual bits by ANDing this byte with the particular bit as one.
for 5th bit
0xDB & (1<<5)
for 6th bit
0xDB & (1<<6)
If you wanted to extract the first byte(4F), you would do
0x4FAEBCDB & (0xFF000000)
FF stands for (1111 1111) and the rest of the bits are 0. So doing the AND operation bitwise will return the byte at the position in which we specified 1s.
Similarly (1<<5) generates 00010000.
Thus doing And operation with this will return the bit value at the particular position.
You need to use the & operator for this.
For example, if your value is in variable int x,
(x & 0xFF000000) >> 24
will provide the 4th byte. In this, if you want to pick just the 5th and 6th bits, you can use
(x & 0x30000000) >> 28
Check out the link http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html for more details.

Combine 2 8 bit byte array positions to a single 16 bit integer

I have a byte array in which a value is stored as a 16bit unsigned integer. This is spread across two positions in my byte array, DataArray[11] and DataArray[12]. The documentation I have for the packet which contains the byte array tells me that the value I need to extract is packed least significant bit first. I'm having trouble wrapping my head around bitmasks and bit shifting, and I'm actually unclear if I need to use one or the other, or both.
This is what I have so far, but the results don't seem right:
int result = (DataArray[11] << 8 | DataArray[12]) & 0xFF;
You're trying to get a 16-bit integer, right? But you're masking it using & 0xff - which limits you to 8 bits. I suggest you mask each byte rather than the result:
int result = (DataArray[11] & 0xff) |
((DataArray[12] & 0xff) << 8);
I've included more parentheses here than are probably required, just for the sake of sanity and not needing to worry about precedence.
I've also swapped the ordering so that you're shifting DataArray[12] rather than DataArray[11], as it's meant to be least-significant byte first.

Understanding signed numbers and complements in java

I have a 3 byte signed number that I need to determine the value of in Java. I believe it is signed with one's complement but I'm not 100% sure (I haven't studied this stuff in more than 10 years and the documentation of my problem isn't super clear). I think the problem I'm having is Java does everything in two's complement. I have a specific example to show:
The original 3-byte number: 0xEE1B17
Parsed as an integer (Integer.parseInt(s, 16)) this becomes: 15604503
If I do a simple bit flip (~) of this I get (I think) a two's complement representation: -15604504
But the value I should be getting is: -1172713
What I think is happening is I'm getting the two's complement of the entire int and not just the 3 bytes of the int, but I don't know how to fix this.
What I have been able to do is convert the integer to a binary string (Integer.toBinaryString()) and then manually "flip" all of the 0s to 1s and vice-versa. When then parsing this integer (Integer.parseInt(s, 16)) I get 1172712 which is very close. In all of the other examples I need to always add 1 to the result to get the answer.
Can anyone diagnose what type of signed number encoding is being used here and if there is a solution other than manually flipping every character of a string? I feel like there must be a much more elegant way to do this.
EDIT: All of the responders have helped in different ways, but my general question was how to flip a 3-byte number and #louis-wasserman answered this and answered first so I'm marking him as the solution. Thanks to everyone for the help!
If you want to flip the low three bytes of a Java int, then you just do ^ 0x00FFFFFF.
0xFFEE1B17 is -1172713
You must only add the leading byte. FF if the highest bit of the 3-byte value is set and 00 otherwise.
A method which converts your 3-byte value to a proper intcould look like this:
if(byte3val>7FFFFF)
return byte3val| 0xFF000000;
else
return byte3val;
Negative signed numbers are defined so that a + (-a) = 0. So it means that all bits are flipped and then 1 added. See Two's complement. You can check that the condition is satisfied by this process by thinking what happens when you add a + ~a + 1.
You can recognize that a number is negative by its most significant bit. So if you need to convert a signed 3-byte number into a 4-byte number, you can do it by checking the bit and if it's set, set also the bits of the fourth byte:
if ((a & 0x800000) != 0)
a = a | 0xff000000;
You can do it also in a single expression, which will most likely perform better, because there is no branching in the computation (branching doesn't play well with pipelining in current CPUs):
a = (0xfffffe << a) >> a;
Here << and >> perform byte shifts. First we shift the number 8 bits to the right (so now it occupies the 3 "upper" bytes instead of the 3 "lower" ones), and then shift it back. The trick is that >> is so-called Arithmetic shift also known as signed shift. copies the most significant bit to all bits that are made vacant by the operation. This is exactly to keep the sign of the number. Indeed:
(0x1ffffe << 8) >> 8 -> 2097150
(0xfffffe << 8) >> 8 -> -2
Just note that java also has a unsigned right shift operator >>>. For more information, see Java Tutorial: Bitwise and Bit Shift Operators.

Categories

Resources