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.
Related
I am working on a file reader and came into a problem when trying to read a short. In short (punintended), java is converting a two bytes I'm using to make the short into an int to do bitwise operations and is converting it in a way to keep the same value. I need to convert the byte into an int in a way that would preserve its value so the bits stayed the same.
example of what's happening:
byte number = -1; //-1
int otherNumber = 1;
number | otherNumber; // -1
example of what I want:
byte number = -1; //-1
int otherNumber = 1;
number | otherNumber; // 129
This can be done pretty easily with some bit magic.
I'm sure you're aware that a short is 16 bits (2 bytes) and an int is 32 bits (4 bytes). So, between an integer and a short, there is a two-byte difference. Now, for positive numbers, copying the value of a short to an int is effectively copying the binary data, however, as you've pointed out, this is not the case for negative numbers.
Now let's look at how negative numbers are represented in binary. It's a bit confusing, so I'll try to keep it simple. Modern systems use what's called the two's compliment to store negative numbers. Basically all this means is that the very first bit in the set of bytes representing the number determines whether or not it's negative. For mathematical purposes, the rest of the bits are also inverted and offset 1 bit to the right (since you can't have negative 0). For example, 2 as a short would be represented as 0000 0000 0000 0010, while -2 would be represented as 1111 1111 1111 1110. Now, since the bytes are inverted in a negative number, this means that -2 in int form is the same but with 2 more bytes (16 bits) at the beginning that are all set to 1.
So, in order to combat this, all we need to do is change the extra 1s to 0s. This can be done by simply using the bitwise and operator. This operator goes through each bit and checks if the bits at each position in each operand are a 1 or a 0. If they're both 1, the bit is flipped to a 0. If not, nothing happens.
Now, with this knowledge, all we need to do is create another integer where the first two bytes are all 1. This is fairly simple to do using hexidecimal literals. Since they are an integer by default, we simply need to use this to get four bytes of 1s. With a single byte, if you were to set every bit to 1, the max value you can get is 255. 255 in hex is 0xFF, so 2 bytes would be 0xFFFF. Pretty simple, now you just need to apply it.
Here is an example that does exactly that:
short a = -2;
int b = a & 0xFFFF;
You could also use Short.toUnsignedInt(), but where's the fun in that? 😉
So I have asmall problem here, and I have no clue what could be wrong.
Thats why I'm asking if this (what I'll show you now) ist correct.
I'm turning Binary Files into Byte Lists, so that I can turn those bytes into half bytes.
For Example:
If I get 96 as decimal number (60 as hexadecimal) I want to get 6 and 0 out of it. The same thing with 127 (hex:7F) - I want to get 7 and 15. To achieve this I wrote the following code:
You'll notice, that I need "unsigned bytes" for this in order to work
System.out.println((byte) ((UnsignedByte.unsignedToBytes(b) - (UnsignedByte.unsignedToBytes(b) % 16)) / 16));
System.out.println((byte) (UnsignedByte.unsignedToBytes(b) % 16));
public static int unsignedToBytes(byte b) {
return b & 0xFF;
}
Am I doing something wrong or is this not a Problem?
Use bit shifting and bitwise operations:
To get the lower four bits, use lowerNibble = wholeByte & 0x0F
To get the upper four bits, use upperNibble = (wholeByte >> 4) & 0x0F
This disregards the sign, because the upper portion of the number is truncated off by & 0x0F.
I have the following code snippet and need some help understanding a few pieces of it.
String fileName = UUID.randomUUID().toString();
int hashcode = fileName.hashCode();
//I'm not sure why we are creating a mask with an int of 255
int mask = 255;
//Wny are we adding 255 to the hashcode?
int firstDir = hashcode & mask;
//What does it mean to have (hashcode >> 8) & mask? If I were to build a third
// tier would I use (hashcode >> 16) $ mask?
int secondDir = (hashcode >> 8) & mask;
StringBuilder sb = new StringBuilder(File.separator);
//I noticed when using this %02 it truncates the directory to 2 chars, does this
//just convert 3 digits to alpha numeric representing the same three digits?
sb.append(String.format("%02x", firstDir));
sb.append(File.separator);
sb.append(String.format("%02x", secondDir));
sb.append(File.separator);
Lastly, if I wanted to generate a file name from the two directories, would I just setup another string builder without the File.separator, or would it be more efficient to build the string first without the file separator, then split up the string?
255 is 0FF hex, 0 1111 1111 binary.
A mask used with the 'and' operator ("&") is used to isolate the bits of the value to which the mask is anded -- an integer anded with the above mask results in an integer with the same lowest-order 8 bits as the original integer.
An integer put through >> 8 is shifted to the right 8 bits; anding with the same mask after that isolates those 8 bits, which started out as the next-higher-order 8 bits in the original integer.
Don't worry about efficiency unless you can show that a few microseconds is going to make a difference. Worry about making your code understandable enough that someone doesn't have to post to stackoverflow to understand it.
That code is just silly.
If you want to create two randomly distributed two-digit hex codes derived from a random UUID, you can just use the first four hex digits of the UUID itself.
String fileName = UUID.randomUUID().toString();
String firstDir = fileName.substring(0,2);
String secondDir = fileName.substring(2,4);
A random UUID is a cryptographically strong random binary string (except for a few fixed digits to denote that this is a type-4 UUID). Any hashing and bit shifting or masking will just degrade the randomness.
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.
I'm using byte arrays (of size 2 or 4) to emulate the effect of short and int data types.
Main idea is to have a data type that support both char and int types, however it is really hard for me to emulate arithmetic operations in this way, since I must do them in bit level.
For those who do not follow:
The int representation of 123 is not equal to the byte[] of {0,1,2,3} since their bit representations differ (123 representation is 00000000000000000000000001111011 and the representation of {0,1,2,3} is 00000000000000010000001000000011 on my system.
So "int of 123" would actually be equivalent to "byte[] of {0,0,0,123}". The problems occur when values stretch over several bytes and I try to subtract or decrement from those byte arrays, since then you have to interact with several different bytes and my math isn't that sharp.
Any pseudo-code or java library suggestions would be welcome.
Unless you really want to know what bits are being carried from one byte to the next, I'd suggest don't do it this way! If it's just plain math, then convert your arrays to real short and int types, do the math, then convert them back again.
If you must do it this way, consider the following:
Imaging you're adding two short variables that are in byte arrays.
The first problem you have is that all Java integer types are signed.
The second is that the "carry" from the least-significant-byte into the most-significant-byte is best done using a type that's longer than a byte because otherwise you can't detect the overflow.
i.e. if you add two 8-bit values, the carry will be in bit 8. But a byte only has bits 0..7, so to calculate bit 8 you have to promote your bytes to the next appropriate larger type, do the add operation, then figure out if it resulted in a carry, and then handle that when you add up the MSB. It's just not worth it.
BTW, I did actually have to do this sort of bit manipulation many years ago when I wrote an MC6809 CPU emulator. It was necessary to perform multiple operations on the same operands just to be able to figure out the effect on the CPU's various status bits, when those same bits are generated "for free" by a hardware ALU.
For example, my (C++) code to add two 8-bit registers looked like this:
void mc6809::help_adc(Byte& x)
{
Byte m = fetch_operand();
{
Byte t = (x & 0x0f) + (m & 0x0f) + cc.bit.c;
cc.bit.h = btst(t, 4); // Half carry
}
{
Byte t = (x & 0x7f) + (m & 0x7f) + cc.bit.c;
cc.bit.v = btst(t, 7); // Bit 7 carry in
}
{
Word t = x + m + cc.bit.c;
cc.bit.c = btst(t, 8); // Bit 7 carry out
x = t & 0xff;
}
cc.bit.v ^= cc.bit.c;
cc.bit.n = btst(x, 7);
cc.bit.z = !x;
}
which requires that three different additions get done on different variations of the operands just to extract the h, v and c flags.