getting 2's complement from a hex string value in java - java

i have a hex value "FF30" in string format.i need the two's complement value of this number.now i am doing,first converting it to binary then taking the 2's complement.is there is any simple way.

Do you need to apply the 2's complement operation to this value, or do you need to just interpret it as a 2's complement number? If the latter, then skip the second line of code below.
I think this will work for you.
int val = Integer.parseInt("FF30", 16);
int result = (~val) + 1;
Update
Since you imply in your comments that you want the result converted back to a string, that's a simple matter of calling "toHexString" and chopping off any padded bits that were prefixed
String hex = "FF30";
int length = hex.length();
long value = Long.parseLong(hex, 16); // convert hex string to long
long result = (~value) + 1; // compute the 2's complement
// convert the result value back to a hex string (keeping the same length and dropping any sign-extension bits)
String resultAsString = Long.toHexString(result);
// chop off the prefix of the string so the result is the same length as the input
int newLength = resultAsString.length();
if (newLength > length)
{
resultAsString = resultAsString.substring(newLength-length);
}
System.out.print(resultAsString);

Related

applying 2's complement in hex string in java

i have hex value 03E7 which is string in type.i need to apply 2s compliment in this string.and the resultant hex value should be in string format.i first converted it to binary then converted .is there is any simple method?
Negative numbers are the 2's complement of positive numbers and vice versa, so I suppose you could parse your string into an int, multiply by -1, and then parse it back into the resulting hex string.
int intVal = Integer.parseInt("03E7", 16);
String twosComplement = Integer.toHexString((-1 * intVal));

convert a hex string to a binary string in byte throws NumberFormatException

public static byte[][] keyArray = new byte[4][4];
String hex = "93";
String hexInBinary = Integer.toBinaryString(Integer.parseInt(hex, 16));
keyArray[row][col] = Byte.parseByte(hexInBinary,2); //this line causes the error
This is the error message I get,
"Exception in thread "main" java.lang.NumberFormatException: Value out of range. Value:"10010011" Radix:2."
I don't want to use getBytes(), because I actually have a long string, "0A935D11496532BC1004865ABDCA42950." I want to read 2 hex at a time and convert to byte.
EDIT:
how I fixed it:
String hexInBinary = String.format("%8s", Integer.toBinaryString(Integer.parseInt(hex, 16))).replace(' ', '0');
keyArray[row][col] = (byte)Integer.parseInt(hexInBinary, 2);
As it is written in the exception message the string you are trying to convert to byte exceeds the max. value of a byte can have.
In your example the string "10010011" equals to 147, but the max value for a byte variable is 2^7 - 1 = 127.
You might want to check the Byte Class documentation;
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Byte.html#MAX_VALUE
So i suggest to use Integer.parseInt(), instead of parseByte method and then cast the int value to byte, integer value 147 will become -109 when you cast it to byte value.
public class ByteConvert {
public static void main(String[] argv) {
String hex = "93";
String hexInBinary = Integer.toBinaryString(Integer.parseInt(hex, 16));
int intResult = Integer.parseInt(hexInBinary,2);
System.out.println("intResult = " + intResult);
byte byteResult = (byte) (Integer.parseInt(hexInBinary,2));
System.out.println("byteResult = " + byteResult);
byte result = Byte.parseByte(hexInBinary,2);
System.out.println("result = " + result);
}
}
C:\JavaTools>java ByteConvert
intResult = 147
byteResult = -109
Exception in thread "main" java.lang.NumberFormatException: Value out of range.
Value:"10010011" Radix:2
at java.lang.Byte.parseByte(Unknown Source)
at ByteConvert.main(ByteConvert.java:9)
As can be seen, parseByte detects a value "larger" than a byte.
According to the java documention at http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Byte.html#parseByte(java.lang.String),
"The characters in the string must all be digits, of the specified radix
(as determined by whether Character.digit(char, int) returns a nonnegative
value) except that the first character may be an ASCII minus
sign '-' ('\u002D') to indicate a negative value."
So the binary representation is not twos-compliment. The byte 10010011 in twos-compliment notation would be negative given that the upper bit is a 1. So if you want to get the same value as the twos-compliment byte 10010011, you would need to do Byte.parseByte("-1101100");.
Put another way, the maximum value an unsigned byte can have is 255. The maximum value a signed byte can have is 127 (because if the most-significant-bit is 1, then it is interpreted as a negative number). However, the issue with parseByte() is that it instead uses an explicit "-" symbol instead of a 1 to indicate negative numbers. This means that the rest of the "byte" can only use 7 bits.

Convert long string to integer without parseLong or parseInt

Here's is the situation ... i have a binary file which contains 32-bit binary strings of characters (e.g 1011011100100110101010101011010 ) and i want to convert this to integer ... I have already tried to do it with parse-Int but if the most significant value is 1, i get back a negative number and i do not want that ... Then i tried it with parse-Long and it was okay but after that when i get this integer i have to send it to another class which can receive only integers , as a result i do casting from long to int and i get back a negative integer again ... The only way to do that is with a piece of code that i found which does the opposite thing ( from int to string ) but i do not understand how to change-convert it. It is about masks which i do not know a lot of things.
Here is the code :
private static String intToBitString(int n) {
StringBuffer sb = new StringBuffer();
for (int mask = 1 << 31; mask != 0; mask = mask >>> 1)
sb.append((n & mask) == 0 ? "0" : "1");
return sb.toString();
}
Thank you in advance...
An integer with the highest bit set to 1 is a negative integer, regardless of the number of bits. Just add the heading zero to the string or alternatively clear the highest bit with bitwise AND (x & 0x7FFFFFFF). You can only store a 31 bit positive integer in java int.
Even if you assign such value to long (long x = 0xFFFFFFFF, will be -1), the sign bit expands and now you have the negative long (you can write 0x0FFFFFFFFL however to assign the expected 00000000FFFFFFFF to long). You still need to clear the high bits if this is unwanted behavior.
int a = 0x80000007; // High bit 1 - negative!
long b = a; // Sign expands!
// Clearing high bits (mind leading 0 and
// the long type suffix (L) in the hex constant:
long c = b & 0x0FFFFFFFFL;
System.out.println(a + ":" + Long.toHexString(b) + ":"
+ Long.toHexString(c));
The output: -2147483641:ffffffff80000007:80000007

Java Byte.parseByte() error

I'm having a small error in my code that I can not for the life of me figure out.
I have an array of strings that are representations of binary data (after converting them from hex) for example:
one index is 1011 and another is 11100. I go through the array and pad each index with 0's so that each index is eight bytes. When I try to convert these representations into actual bytes I get an error when I try to parse '11111111' The error I get is:
java.lang.NumberFormatException: Value out of range. Value:"11111111" Radix:2
Here is a snippet:
String source = a.get("image block");
int val;
byte imageData[] = new byte[source.length()/2];
try {
f.createNewFile();
FileOutputStream output = new FileOutputStream(f);
for (int i=0; i<source.length(); i+=2) {
val = Integer.parseInt(source.substring(i, i+2), 16);
String temp = Integer.toBinaryString(val);
while (temp.length() != 8) {
temp = "0" + temp;
}
imageData[i/2] = Byte.parseByte(temp, 2);
}
Isn't the problem here that byte is a signed type, therefore its valid values are -128...127? If you parse it as an int (Using Integer.parseInt()), it should work.
By the way, you don't have to pad the number with zeroes either.
Once you parsed your binary string into an int, you can cast it to a byte, but the value will still be treated as signed, so binary 11111111 will become int 255 first, then byte -1 after the cast.
Well, eight one's is 255, and according to java.lang.Byte, the MAX_VALUE is 2^7 - 1 or positive 127.
So your code will fail because you number is too large. The first bit is reserved for the positive and negative sign.
according to parseByte
byte's only allow numbers in the range of -128 to 127. I would use an int instead, which holds numbers in the range of -2.1 billion to 2.1 billion.

Java negative BigInteger toString

It seems I have a two's complement issue with Java's BigInteger.
I have a 64-bit integer where only the msb and the second msb are set to 1, the rest is 0.
In decimal this comes up to: -4611686018427387904
The Java side of my application receives this decimal number as a string, and converts it to BigInteger like so:
BigInteger bi = new BigInteger("-4611686018427387904", 10);
Then, it needs to display this number both in binary and hex forms.
I tried to use:
String bin = bi.toString(2);
String hex = bi.toString(16);
but I'm getting:
-100000000000000000000000000000000000000000000000000000000000000
-4000000000000000
whereas I expect to get:
1100000000000000000000000000000000000000000000000000000000000000
c000000000000000
Any tips?
Number always fits in 64 bits:
If your number always fits in 64 bits you can put it in a long and then print the bits / hex digits.
long l = bi.longValue();
String bin = Long.toBinaryString(l);
String hex = Long.toHexString(l);
System.out.println(bin);
System.out.println(hex);
Number may not always fit in 64 bits:
If the number does not always fit in 64 bits, you'll have to solve it "manually". To convert a number to it's two's complement representation you do the following:
If number is positive, do nothing
If number is negative:
Convert it to its absolute value
Complement the bits
Add 1
For a BigInteger the conversion looks as follows:
if (bi.compareTo(BigInteger.ZERO) < 0)
bi = bi.abs().not().add(BigInteger.ONE);
If you print it using bi.toString(2) you'll still get the sign character, instead of a leading 1. This can be solved by simply appending .replace('-', '1') to the string.
There is a BigInteger.toByteArray() method, that returns two's complement representation of BigInteger as a byte[]. All you need is to print that array in hex or binary form:
byte[] bs = bi.toByteArray();
for (byte b: bs) {
System.out.print(String.format("%02X", 0xff & b));
}
The binary number 1100000000000000000000000000000000000000000000000000000000000000 is definitely a positive number, right. It's equal to 2^63 + 2^62.
I don't see why you'd expect a negative number to become positive when you convert to base 2 or base 16.
You are confusing the base n representation with the internal representation of numbers.
If the number is 64 bits or less, then the simple way to solve this is to convert to a long and then use Long.toHexString().
what you mean?
Do you want to get Two's complement?
if you mean that, maybe i can give you an example
import java.util.*;
public class TestBina{
static void printBinaryInt(int i){
System.out.println("int:"+i+",binary:");
System.out.print(" ");
for(int j=31;j>=0;j--)
if(((1<<j)&i)!=0)
System.out.print("1");
else
System.out.print("0");
System.out.println();
}
public static void main(String [] args){
Random rand = new Random();
int i = rand.nextInt();
int j = rand.nextInt();
printBinaryInt(i);
printBinaryInt(j);
printBinaryInt(10);
printBinaryInt(-10);
}
}

Categories

Resources