Convert integer to byte in java - 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));
}

Related

Bit shuffling to change encoding from little endian

So in the program I need to read an number from the user which needs to be changed from little endian encoding to whatever encoding the user wants to change it to. The encoding entered by the user is just a 4 digits number which just means which byte should be where after the encoding. e.g. 4321 means put the 4th byte first followed by the 3rd and so on. the encoding can take other form such as 3214 etc.
This is my code, would really appreciate if someone point out where I am missing out.
import java.util.Scanner;
class encoding {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String byteOrder = sc.next();
long[] bitMask = { // little endian
Long.parseLong("11111111000000000000000000000000", 2),
Long.parseLong("00000000111111110000000000000000", 2),
Long.parseLong("00000000000000001111111100000000", 2),
Long.parseLong("00000000000000000000000011111111", 2)
};
int[] bytes = {
(int)(bitMask[0] & n),
(int)(bitMask[1] & n),
(int)(bitMask[2] & n),
(int)(bitMask[3] & n)
};
int result = 0;
shuffleBytes(bytes, byteOrder);
for (int i = 0; i < 4; i++) {
bytes[i] = bytes[i] << (i * 8);
result |= bytes[i];
}
System.out.println(result);
}
static void shuffleBytes(int[] bytes, String encoding) {
for (int i = 0; i < 4; i++) {
int index = Integer.parseInt(encoding.substring(i, i+1))-1;
int copy = bytes[i];
bytes[i] = bytes[index];
bytes[index] = copy;
}
}
}
Fixing your current solution
There are two problems:
1. Forgot to right-align bytes
In ...
int[] bytes = {
(int)(bitMask[0] & n),
(int)(bitMask[1] & n),
(int)(bitMask[2] & n),
(int)(bitMask[3] & n)
};
... you forgot to shift each "byte" to the right. As a result, you end up with a list of "bytes" of the form 0x……000000, 0x00……0000, 0x0000……00, 0x000000……. This is not a problem yet, but after shuffleBytes you shift each of these entries again using bytes[i] = bytes[i] << (i * 8);. As a result, the relevant parts (__) end up at a completely different spot or are shifted completely out of the integer.
To fix this, shift each (int)(bitMask[…] & n) to the right:
int[] bytes = {
(int)(bitMask[0] & n) >> (3*8),
(int)(bitMask[1] & n) >> (2*8),
(int)(bitMask[2] & n) >> (1*8),
(int)(bitMask[3] & n) >> (0*8)
};
2. Swapping more than once
In ...
static void shuffleBytes(int[] bytes, String encoding) {
for (int i = 0; i < 4; i++) {
int index = Integer.parseInt(encoding.substring(i, i+1))-1;
int copy = bytes[i];
bytes[i] = bytes[index];
bytes[index] = copy;
}
}
... you swap some bytes multiple times because you operate in-place. To understand what happens consider the following minimal example where we want to swap two bytes using order = "21". We inspect the variables before/after each iteration of the for loop.
The original input is bytes = {x, y} and order = "21"
We moved bytes[0] to bytes[1]. Now we have bytes = {y, x}.
But we are not finished yet. The loop continues and moves bytes[1] to bytes[0]. You assumed that bytes[1] would still be y at this point. However, because of the previous iteration this entry now holds x instead. Therefore, the result is bytes = {x, y}.
Here nothing changed, but for more entries you might also end up with something that is neither the original order nor the expected output order.
The easiest way to fix this is to write the result into a new array:
static int[] shuffleBytes(int[] bytes, String encoding) {
int[] result = new int[bytes.length];
for (int i = 0; i < 4; i++) {
int index = Integer.parseInt(encoding.substring(i, i+1))-1;
result[index] = bytes[i];
}
return result; // also adapt main() to use this return value
}
Alternative Solution
Even though you could fix your solution as described above I'm not too happy with it. Therefore, I propose this alternative solution which is cleaner, shorter, and more efficient.
import java.util.Scanner;
public class Encoding {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int input = sc.nextInt();
System.out.format("input = 0x%08x = %1$d%n", input);
String newOrder = sc.next();
int output = reorder(input, newOrder);
System.out.format("output = 0x%08x = %1$d%n", output);
}
/** #param newOrder permutation of "1234" */
static int reorder(int input, String newOrder) {
int output = 0;
for (char byte1Based : newOrder.toCharArray()) {
output <<= 8;
int shift = (byte1Based - '1') * 8;
output |= ((0xFF << shift) & input) >> shift;
}
return output;
}
}

Java Convert integer to hex integer

I'm trying to convert a number from an integer into an another integer which, if printed in hex, would look the same as the original integer.
For example:
Convert 20 to 32 (which is 0x20)
Convert 54 to 84 (which is 0x54)
The easiest way is to use Integer.toHexString(int)
public static int convert(int n) {
return Integer.valueOf(String.valueOf(n), 16);
}
public static void main(String[] args) {
System.out.println(convert(20)); // 32
System.out.println(convert(54)); // 84
}
That is, treat the original number as if it was in hexadecimal, and then convert to decimal.
Another way to convert int to hex.
String hex = String.format("%X", int);
You can change capital X to x for lowercase.
Example:
String.format("%X", 31) results 1F.
String.format("%X", 32) results 20.
int orig = 20;
int res = Integer.parseInt(""+orig, 16);
You could try something like this (the way you would do it on paper):
public static int solve(int x){
int y=0;
int i=0;
while (x>0){
y+=(x%10)*Math.pow(16,i);
x/=10;
i++;
}
return y;
}
public static void main(String args[]){
System.out.println(solve(20));
System.out.println(solve(54));
}
For the examples you have given this would calculate: 0*16^0+2*16^1=32 and 4*16^0+5*16^1=84
String input = "20";
int output = Integer.parseInt(input, 16); // 32
The following is optimized iff you only want to print the hexa representation of a positive integer.
It should be blazing fast as it uses only bit manipulation, the utf-8 values of ASCII chars and recursion to avoid reversing a StringBuilder at the end.
public static void hexa(int num) {
int m = 0;
if( (m = num >>> 4) != 0 ) {
hexa( m );
}
System.out.print((char)((m=num & 0x0F)+(m<10 ? 48 : 55)));
}
Simply do this:
public static int specialNum(num){
return Integer.parseInt( Integer.toString(num) ,16)
}
It should convert any special decimal integer to its hexadecimal counterpart.

How could I convert a 64-width binary string to long in Java?

I want to convert a 64-width binary string to long, there is a static method:
Long.parseLong(String s, int radix)
to do this, but it isn't suitable for my case.
The problem is my binary string is a machine-style long int.
For example:
1111111111111111111111111111111111111111111111111111111110000101
represents -123, but this method recognize it as a huge positive number, this troubles me, how could I solve this problem?
Must I write a function that does the complement?
You can use BigInteger
public static void main(String... args) {
String s = "1111111111111111111111111111111111111111111111111111111110000101";
long l = parseLong(s, 2);
System.out.println(s +" => " + l);
String s2 = s.substring(1);
long l2 = parseLong(s2, 2);
System.out.println(s2 +" => " + l2);
}
private static long parseLong(String s, int base) {
return new BigInteger(s, base).longValue();
}
prints
1111111111111111111111111111111111111111111111111111111110000101 => -123
111111111111111111111111111111111111111111111111111111110000101 => 9223372036854775685
My incredibly hacked-together solution, tested only on your case:
public static long makeLong(String input) {
if(input.substring(0,1).equals("1")) {
return -1 * (Long.MAX_VALUE - Long.parseLong(input.substring(1), 2) + 1);
} else {
return Long.parseLong(input, 2);
}
}
Basically, if the first bit is a one, the number is negative, so we parse the rest of the number as a positive, then do some two's complement magic by subtracting that result from Long.MAX_VALUE and adding one, then forcing the negative back onto the number returned. Otherwise, the normal conversion applies.
You could just set the bits yourself...
assert string.length() == 64;
long result = 0;
for (int i = 0; i < 64; ++i) {
char c = string.charAt(63-i);
switch (c) {
case '1': result |= (1L << i); break;
case '0'; break;
default: throw new WhateverException("bad char " + c);
}
}
EDIT: I originally had 1 << i, which means the shifting is being done as an int. Fixed to make it being done as a long.
I don't think there's a library function to do what you want, but this should work:
long num = 0L;
for (int i = 0; i < 64; i++) {
if (yourString.charAt(i) == '1') {
num ^= 1L << (63 - i);
}
}
Of course, you should check to make sure that the string is length 64 and contains only 0 and 1.

Decimal-to-binary conversion

I want to convert decimal numbers to binary numbers. I want to store them in an array.
First I need to create an array that has a certain length so that I can store the binary numbers. After that I perform the conversion, here is how I do it:
public class Aufg3 {
public static void main(String[] args) {
int[] test = decToBin(12, getBinArray(12));
for(int i = 0; i < test.length; i++){
System.out.println(test[i]);
}
}
public static int[] getBinArray(int number){
int res = number, length = 0;
while(res != 0){
res /= 2;
length++;
}
return new int[length];
}
public static int[] decToBin(int number, int[] array){
int res = number, k = array.length-1;
while(res != 0){
if(res%2 == 0){
array[k] = 0;
}else{
array[k] = 1;
}
k--;
res /= 2;
}
return array;
}
}
Is there anything to improve? It should print 1100 for input of 12.
Why not just use the toBinaryString method of the Integer class:
System.out.println(Integer.toBinaryString(12))
I assume you want to write your own code -- otherwise this is straightforward to do using methods from the standard Java library.
Some quick comments:
You can get rid of the res temp vars. Work directly on number (remember that Java passes parameters by value).
Shift is more efficient than division (number >>>= 1 instead of number /= 2), although the compiler should be able to optimize this anyway
You can avoid the modulus in decToBin if you just do array[k] = number & 1;
While you are at it, why not call getBinArray from decToBin directly? Then you can call decToBin with only one arg -- the value to convert.
Here is a slightly optimized version of your code:
public static int[] getBinArray(int number) {
int length = 0;
while (number != 0) {
number >>>= 1;
length++;
}
return new int[length];
}
public static int[] decToBin(int number) {
int[] array = getBinArray(number);
int k = array.length-1;
while (number != 0)
{
array[k--] = number & 1;
number >>>= 1;
}
return array;
}
If this isn't homework, no need to do it yourself. The following code should work:
BigInteger bigInt = new BigInteger(number);
String asString = bigInt.toString(2);
There might be more efficient ways, but this is certainly very readable and maintainable.
There are some small things that you can improve:
You should define a "high-level" method that converts an int to an int[]. In the current code you have to mention the 12 two times, which is bad.
You should use a do { ... } while (number != 0) loop. Otherwise the number 0 will be represented by an empty array.
You should use x >>> 1 instead of x / 2, since that handles negative numbers correctly.
If you want to check that your code is correct, write another method that converts back from binary to int. Then you can check that binToDec(decToBin(12, ...)) == 12.
The method getBinArray should not be public, since it is only a helper method. You can either replace the public with private or just remove the public.

A question in java.lang.Integer internal code

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

Categories

Resources