The question has been answered for integers printed in decimal format, but I'm looking for an elegant way to do the same with integers in non-decimal format (like binary, octal, hex).
Creation of such Strings is easy:
String intAsString = Integer.toString(12345, 8);
would create a String with the octal represenation of the integer value 12345. But how to format it so that the String has like 10 digits, apart from calculating the number of zeros needed and assembling a new String 'by hand'.
A typical use case would be creating binary numbers with a fixed number of bits (like 16, 32, ...) where one would like to have all digits including leading zeros.
For oct and hex, it's as easy as String.format:
assert String.format("%03x", 16) == "010";
assert String.format("%03o", 8) == "010";
With Guava you could just write:
String intAsString = Strings.padStart(Integer.toString(12345, 8), 10, '0');
How about this (standard Java):
private final static String ZEROES = "0000000000";
// ...
String s = Integer.toString(12345, 8);
String intAsString = s.length() <= 10 ? ZEROES.substring(s.length()) + s : s;
Printing out a HEX number, for example, with ZERO padding:
System.out.println(String.format("%08x", 1234));
Will give the following output, with the padding included:
000004d2
Replacing x with OCTAL's associated formatting character will do the same, probably.
Here's a more reuseable alternative with help of StringBuilder.
public static String padZero(int number, int radix, int length) {
String string = Integer.toString(number, radix);
StringBuilder builder = new StringBuilder().append(String.format("%0" + length + "d", 0));
return builder.replace(length - string.length(), length, string).toString();
}
The Guava example as posted by ColinD is by the way pretty slick.
Related
Below is a snippet of my java code.
//converts a binary string to hexadecimal
public static String binaryToHex (String binaryNumber)
{
BigInteger temp = new BigInteger(binaryNumber, 2);
return temp.toString(16).toUpperCase();
}
If I input "0000 1001 0101 0111" (without the spaces) as my String binaryNumber, the return value is 957. But ideally what I want is 0957 instead of just 957. How do I make sure to pad with zeroes if hex number is not 4 digits?
Thanks.
You do one of the following:
Manually pad with zeroes
Use String.format()
Manually pad with zeroes
Since you want extra leading zeroes when shorter than 4 digits, use this:
BigInteger temp = new BigInteger(binaryNumber, 2);
String hex = temp.toString(16).toUpperCase();
if (hex.length() < 4)
hex = "000".substring(hex.length() - 1) + hex;
return hex;
Use String.format()
BigInteger temp = new BigInteger(binaryNumber, 2);
return String.format("%04X", temp);
Note, if you're only expecting the value to be 4 hex digits long, then a regular int can hold the value. No need to use BigInteger.
In Java 8, do it by parsing the binary input as an unsigned number:
int temp = Integer.parseUnsignedInt(binaryNumber, 2);
return String.format("%04X", temp);
The BigInteger becomes an internal machine representation of whatever value you passed in as a String in binary format. Therefore, the machine does not know how many leading zeros you would like in the output format. Unfortunately, the method toString in BigInteger does not allow any kind of formatting, so you would have to do it manually if you attempt to use the code you showed.
I customized your code a bit to include leading zeros based on input string:
public static void main(String[] args) {
System.out.println(binaryToHex("0000100101010111"));
}
public static String binaryToHex(String binaryNumber) {
BigInteger temp = new BigInteger(binaryNumber, 2);
String hexStr = temp.toString(16).toUpperCase();
int b16inLen = binaryNumber.length()/4;
int b16outLen = hexStr.length();
int b16padding = b16inLen - b16outLen;
for (int i=0; i<b16padding; i++) {
hexStr=('0'+hexStr);
}
return hexStr;
}
Notice that the above solution counts up the base16 digits in the input and calculates the difference with the base16 digits in the output. So, it requires the user to input a full '0000' to be counted up. That is '000 1111' will be displayed as 'F' while '0000 1111' as '0F'.
I want to hash a word into fixed bit hash value say 64 bit,32 bit (binary).
I used the following code
long murmur_hash= MurmurHash.hash64(word);
Then murmur_hash value is converted into binary by the following function
public static String intToBinary (int n, int numOfBits) {
String binary = "";
for(int i = 0; i < numOfBits; ++i) {
n/=2;
if(n%2 == 0)
{
binary="0"+binary;
}
else
binary="1"+binary;
}
return binary;
}
Is there any direct hash method to convert into binary?
Just use this
Integer.toBinaryString(int i)
If you want to convert into a fixed binary string, that is, always get a 64-character long string with zero padding, then you have a couple of options. If you have Apache's StringUtils, you can use:
StringUtils.leftPad( Long.toBinaryString(murmurHash), Long.SIZE, "0" );
If you don't, you can write a padding method yourself:
public static String paddedBinaryFromLong( long val ) {
StringBuilder sb = new StringBuilder( Long.toBinaryString(val));
char[] zeros = new char[Long.SIZE - sb.length()];
Arrays.fill(zeros, '0');
sb.insert(0, zeros);
return sb.toString();
}
This method starts by using the Long.toBinaryString(long) method, which conveniently does the bit conversion for you. The only thing it doesn't do is pad on the left if the value is shorter than 64 characters.
The next step is to create an array of 0 characters with the missing zeros needed to pad to the left.
Finally, we insert that array of zeros at the beginning of our StringBuilder, and we have a 64-character, zero-padded bit string.
Note: there is a difference between using Long.toBinaryString(long) and Long.toString(long,radix). The difference is in negative numbers. In the first, you'll get the full, two's complement value of the number. In the second, you'll get the number with a minus sign:
System.out.println(Long.toString(-15L,2));
result:
-1111
System.out.println(Long.toBinaryString(-15L));
result:
1111111111111111111111111111111111111111111111111111111111110001
Another other way is using
Integer.toString(i, radix)
you can get string representation of the first argument i in the radix ( Binary - 2, Octal - 8, Decimal - 10, Hex - 16) specified by the second argument.
I was playing a bit with numbers, and something interesting came upon me, which I don't quite understand.
public static void main(String[] args) {
int hexNumber = 0x7A;//decimal: 122 binary:0111 1010
int decNumber = 122;
int binNumber = 1111010;
System.out.println(hexNumber);//122
System.out.println(Integer.toString(hexNumber, 16)); //7a
System.out.println(Integer.toHexString(hexNumber)); //7a
System.out.println(Integer.toString(hexNumber, 2)); // 1111010
System.out.println(Integer.toBinaryString(hexNumber)); //1111010
System.out.println(hexNumber==binNumber);//false
System.out.println(hexNumber==decNumber);//true
System.out.println(decNumber==binNumber);//false
}
Why do I get "false" at #1 and #3? Doesn't change even if binNumber = 01111010;
Well, you can't directly store binary values in Java without any prefix.
binNumber isn't stored as the binary number 1111010; instead, it's stored as the decimal number 1111010.
This you have to store as int binNumber = Integer.parseInt("1111010", 2); or better yet int binNumber = 0b1111010;.
For octal:
int octalNo = 0177; //'0' is prefix
or
int octalNo = Integer.parseInt("0177", 8); //leading '0's are ignored
For hexadecimal:
int hexNo = 0x177; //'0x' is prefix
or
int hexNo = Integer.parseInt("0177", 16); //leading '0's are ignored
For more info, have a look at this.
You aren't creating the binary number as a binary one. You are creating it as a decimal one (base 10) that happens to only contain 0s and 1s.
To store 0111 1010 in Java 7 use the new binary literal (you can even use underscores for easier reading)
int binNumber = 0b0111_1010;
Because that's not the proper way to specify the binary number (and there is no such way in Java, apart from something like Integer.toBinaryString(122) which would give you a proper binary representation (returned as a String)).
Your number was interpreted as a "normal" decimal integer (if entered without leading 0) or as an integer in octal system (if entered with leading 0).
In Java versions before 7, you need to use this
int binNumber = Integer.parseInt("1111010", 2);
In 7 and up, you can use
int binNumber = 0b1111010;
With that change, your code works here (I get three true resuls).
The answer is clear. You have assigned to integers some diferent values.hexNumber is initialized to decimal value 122, even if the representation you use for that is hexadecimal. decNumber is initialized to decimal value 122, so when you compare hexNumber and decNumber you will get true because it's really the same value. Finally binNumber is initialized to the decimal value 1111010, so if you compare it with one of the other numbers you will get false.
Integer.toBinaryString(data)
gives me a binary String representation of my array data.
However I would like a simple way to add leading zeros to it, since a byte array equal to zero gives me a "0" String.
I'd like a one-liner like this:
String dataStr = Integer.toBinaryString(data).equals("0") ? String.format(format, Integer.toBinaryString(data)) : Integer.toBinaryString(data);
Is String.format() the correct approach? If yes, what format String should I use?
Thanks in advance!
Edit: The data array is of dynamic length, so should the number of leading zeros.
For padding with, say, 5 leading zeroes, this will work:
String.format("%5s", Integer.toBinaryString(data)).replace(' ', '0');
You didn't specify the expected length of the string, in the sample code above I used 5, replace it with the proper value.
EDIT
I just noticed the comments. Sure you can build the pattern dynamically, but at some point you have to know the maximum expected size, depending on your problem, you'll know how to determine the value:
String formatPattern = "%" + maximumExpectedSize + "s";
This is what you asked for—padding is added only when the value is zero.
String s = (data == 0) ? String.format("%0" + len + 'd', 0) : Integer.toBinaryString(data);
If what you really want is for all binary values to be padded so that they are the same length, I use something like this:
String pad = String.format("%0" + len + 'd', 0);
String s = Integer.toBinaryString(data);
s = pad.substring(s.length()) + s;
Using String.format() directly would be the best, but it only supports decimal, hexadecimal, and octal, not binary.
You could override that function in your own class:
public static String toBinaryString(int x){
byte[] b = new byte[32]; // 32 bits per int
int pos = 0;
do{
x = x >> 1; // /2
b[31-pos++] = (byte)(x % 2);
}while(x > 0);
return Arrays.toString(b);
}
would this satisfy your needs?
String dataStr = data == 0 ? "00" + Integer.toBinaryString(data) : Integer.toBinaryString(data);
edit: noticed the comment about dynamic length:
probably some of the other answers are more suited:)
This, in concept, is almost same as #Óscar López answer, but different methods are used, so i thought i should post it. Hope this is fine.
1] Building the format string
String format = "%0" + totalDigits + "d";
2] Integer to Binary Conversion
String dataStr = Integer.toBinaryString(data);
3] Padding with Leading Zeros
dataStr = String.format(format, new Integer(dataStr));
The major difference here is the 3rd step. I believe, its actually a hack.
#erickson is right in String.format() not supporting binary, hence, i converted the binary number to an integer (not its equivalent), i.e., "100" will be converted to hundred (100), not four(4). I then used normal formatting.
Not sure about how much optimized this code is, but, i think its more easy to read, but, maybe, its just me.
EDIT
1] Buffer Over-run is possible for longer binary strings. Long can be used, but, even that has limitations.
2] BigInteger can be used, but, I'm sure, it will be the costliest at runtime compared to all the other methods.
So, it seems, unless only shorter binary strings are expected, replace() is the better method.
Seniors,
please correct me if I'm wrong.
Thanks.
So I have a set of base digits like "BCDFGHJKLMNPQRSTVWXZ34679"
how do I convert a value say "D6CN96W6WT" to binary string in Java?
This should work (assuming 0,1 for you binary digits):
// your arbitrary digits
private static final String DIGITS = "BCDFGHJKLMNPQRSTVWXZ34679";
public String base25ToBinary(String base25Number) {
long value = 0;
char[] base25Digits = base25Number.toCharArray();
for (char digit : base25Digits) {
value = value * 25 + DIGITS.indexOf(digit);
}
return Long.toString(value, 2);
}
Off the top of my head, for base-25 strings.
Integer.toString(Integer.valueof(base25str, 25), 2)
Its a little unclear from your question whether you're talking about actual 0-9-Z bases, or a number encoding with an arbitrary list of symbols. I'm assuming the first, if its the later then you're out of luck on built-ins.