A question in java.lang.Integer internal code - java

While looking in the code of the method:
Integer.toHexString
I found the following code :
public static String toHexString(int i) {
return toUnsignedString(i, 4);
}
private static String toUnsignedString(int i, int shift) {
char[] buf = new char[32];
int charPos = 32;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[--charPos] = digits[i & mask];
i >>>= shift;
} while (i != 0);
return new String(buf, charPos, (32 - charPos));
}
The question is, in toUnsignedString, why we create a char arr of 32 chars?

32 characters is how much you need to represent an int in binary (base-2, shift of 1, used by toBinaryString).
It could be sized exactly, but I guess it has never made business sense to attempt that optimisation.

Because that method is also called by toBinaryString(), and an int is up to 32 digits in binary.

Because the max value for an int in Java is : 2^31 - 1

Related

How to encode chars in 2-bits? in java

DNA molecules are denoted by one of four values: A, C, G, or T. I need to convert a string of characters from A, C, G, and T to an array of bytes, encoding each of the characters
with two bits.A with bits 00, C with bits 01, G with 10, and T with 11. I don't understand how to convert characters to 2 bits. I was trying to shift and mask, but got wrong result.
At the very beginning, I check if there are characters in the line. Then i convert each character into a bit value and insert it into an array. When i insert ACGT, in the output i got 0 1 3 2. And here I have a problem, because I don’t understand how to convert the value to 2 bits.
Scanner text = new Scanner(System.in);
String str = text.nextLine();
if (str.contains("A") && str.contains("C") && str.contains("G") && str.contains("T")){
System.out.println("");
}
else
{
System.out.println("wrong command format");
}
byte mas[] = str.getBytes();
System.out.println("String in byte array : " + Arrays.toString(mas));
for (int i = 0; i < mas.length; i++){
byte mask = 3;
byte number = mas[i];
byte result = (byte)((number >> 1) & mask);
System.out.println(result);
}
}
}
It seems that you want to save the bits in a byte. The following example might give some ideas.
public class Main
{
private static final int A = 0x00; // b00
private static final int C = 0x01; // b01
private static final int G = 0x02; // b10
private static final int T = 0x03; // b11
public static void main(String[] args) throws Exception
{
byte store = 0;
store = setByte(store, 0, A);
store = setByte(store, 1, C);
store = setByte(store, 2, G);
store = setByte(store, 3, T);
System.out.println(Integer.toBinaryString(store));
//11111111111111111111111111100100
System.out.println(getByte(store, 0)); //0
System.out.println(getByte(store, 1)); //1
System.out.println(getByte(store, 2)); //2
System.out.println(getByte(store, 3)); //3
}
//Behavior :: Store "value" into "store".
//Reminder :: Valid index 0 - 3. Valid value 0 - 3.
private static byte setByte(byte store, int index, int value)
{
store = (byte)(store & ~(0x3 << (2 * index)));
return store |= (value & 0x3) << (2 * index);
}
private static byte getByte(byte store, int index)
{
return (byte)((store >> (2 * index)) & 0x3);
}
}
I haven't tested this, but it may help you.
byte test = 69;
byte insert = 0b01;
byte index = 2;
final byte ones = 0b00000011;
//Clear out the data at specified index
test = (byte) (test & ~(ones << index));
//Insert data
test |= (byte) (insert << index);
It works as follows:
Clear the 2 bits at the index in the byte (using bitwise AND).
Insert the 2 data bits at the index in the byte using bitwise OR).
You can "convert" the chars ACGT to 0, 1, 2, 3 using bit arithmetic.
byte[] bytes = str.getBytes();
for (int i = 0; i < bytes.length; i++) {
bytes[i] = (byte)(bytes[i] >> 1 & 3 ^ bytes[i] >> 2 & 1);
}
I suspect your initial check should be:
if (!str.matches("[ACGT]+") {
System.out.println("wrong command format");
return;
}

How to manipulate the bits in a long?

I want to transform a long to binary code, then change some bits and get the long again. I have found this post Java long to binary but I still can't achieve what I want.
I think there is two ways to achieve my goal:
Going from long to bitset and to long again
Going from long to binary String and then to int array and then to long again
public static long changeHalf(long x){
int[] firstHalf = new int[32];
int[] secondHalf = new int[32];
int[] result = new int[64];
String binaryOfLong = Long.toBinaryString(x);
for (int i = 0; i < firstHalf.length; i++) {
}
for (int i = 0; i < secondHalf.length; i++) {
result[i] = secondHalf[i];
}
for (int i = 0; i < firstHalf.length; i++) {
result[i+32] = firstHalf[i];
}
String s = Arrays.toString(result);
return Long.parseLong(s);
}
Rather than converting a long to arrays of int, just use bitwise operations.
I want to swap the first 32 bits with the last 32 bits
That would be:
long result = ((x & 0xFFFFFFFF00000000l) >> 32) | ((x & 0x00000000FFFFFFFFl) << 32);
That masks off the first 32 bits, shifts them to the right, masks off the last 32 bits, shifts them to the left, and combines the result with | (OR).
Live example:
class Example
{
public static void main (String[] args) throws java.lang.Exception
{
long x = 0x1000000020000000l;
long result = ((x & 0xFFFFFFFF00000000l) >> 32) | ((x & 0x00000000FFFFFFFFl) << 32);
System.out.printf("0x%016X\n", x);
System.out.printf("0x%016X\n", result);
}
}
Outputs:
0x1000000020000000
0x2000000010000000
More in the Bitwise and Bit Shift Operators tutorial.

Java: manipulate bits in a number

I was trying to implement a bit manipulation tool in Java.
I do not want to work with the Bitsetclass.
I am working with 64-bit Long values and implemented the following methods:
static final long toggle_bit(long number, int index) {
return (number ^= (1 << index));
}
static final long set_bit(long number, int index) {
return (number |= (1 << index));
}
static final long unset_bit(long number, int index) {
return (number &= ~(1 << index));
}
static final void print_bits(long number) {
String s = Long.toBinaryString(number);
String zeros = "0000000000000000000000000000000000000000000000000000000000000000"; //String of 64 zeros
s = zeros.substring(s.length()) + s;
System.out.println(s);
}
I think the best way of showing my problem is the result of this code:
>>> print_bits(set_bit(0L, 30));
0000000000000000000000000000000001000000000000000000000000000000
>>> print_bits(set_bit(0L, 31));
1111111111111111111111111111111110000000000000000000000000000000
I assume I am reaching negative values or something like that. I would
be very happy if someone could show me a very efficient way of
manipulating all 64 bits in a long-number.
Greetings,
Finn
Make index and the1 a long (declare as 1L) so that JVM doesn’t treat it as an integer.
I also have to note that in set_bits, |= (or equals) doesn’t account for when the bit is 1 but the desired value at the bit is 0
You are shifting an int value of 1. Try shifting a long value of 1, i.e. 1L << index

Convert integer to byte in java

I am looking for a way to convert an integer value (like 22, 32, 42) to the corresponding fake hex value (like 0x22, 0x32, 0x42).
Can anyone have a solution for this type of problem?
If you just want the 0x appended: "0x"+value. If you want to convert the int to the appropriate number for that hex value
String temp = Integer.toString(value);
int asHex = Integer.valueOf(temp, 16);
I don't know why you want this, it seems strange you won't ever output 0xA through 0xF (because it can't be in the input) but here it is anyway, I hope it at least helps you spot the probable flaw in your approach:
public static int fakeHex(int i) {
int result = 0;
int base = 1;
while (i > 0) {
int decimalDigit = i % 10;
result += base * decimalDigit;
i /= 10;
base *= 16;
}
return result;
}
Test cases:
#Test
public void fake_hex_test() {
assertEquals(0x0, fakeHex(0));
assertEquals(0x9, fakeHex(9));
assertEquals(0x22, fakeHex(22));
assertEquals(0x32, fakeHex(32));
assertEquals(0x42, fakeHex(42));
assertEquals(0x123, fakeHex(123));
}

swapping the order of a multibyte

I have the following multi-byte represented in hex format:
0xdc, 0xd3
I can process the bytes in little endian () format to get the decimal value 54236:
List<Integer> packet = new LinkedList<Integer>(Arrays.asList(0xdc, 0xd3 ));
int idx=0;
int rpm = (int)readBytes(packet, idx, 2);
private long readBytes(List<Integer> packet, int idx, int size){
long val=0;
int element;
for(int i=0;i<size;i++, idx++){
element = packet.get(idx);
val |= element << (8 * i);
}
return val;
}
The above method produces the value as expected. However, now I want to get the value in the reverse order (big endian format), but it gives me some crazy value of 14471936:
private long bigEndianReadBytes(List<Integer> packet, int idx, int size){
long val=0;
int element;
for(int i=size;i>0;i--, idx++){
element = packet.get(idx);
val |= element << (8 * i);
}
return val;
}
What might be wrong with this method?
With #TimBiegeleisen answer (+1), you have good "manual" code to for converting bytes to values.
Have you considered using a ByteBuffer? It does all this for you and works with both Big Endian and Little Endian.
public static void main(String[] args) throws Exception {
ByteBuffer bb = ByteBuffer.allocate(2);
bb.put(new byte[] {(byte)0xdc, (byte)0xd3});
System.out.println(bb.order(ByteOrder.BIG_ENDIAN).getShort(0) & 0xFFFF);
System.out.println(bb.order(ByteOrder.LITTLE_ENDIAN).getShort(0) & 0xFFFF);
}
ANDing the result against 0xFFFF so the short result is promoted to an int, otherwise the result is a negative number because java works with signed data types.
Results:
56531
54236
The for loop in your bigEndianReadBytes() method should start by shifting size - 1 bytes, and end by shifting zero bytes (in the last iteration). Currently, you are shifting size bytes in the first iteration, and one byte in the last iteration. Try this code instead:
for (int i=size-1; i >= 0; i--, idx++) {
element = packet.get(idx);
val |= element << (8 * i);
}

Categories

Resources