如何在Java中获取整数的0填充二进制表示?

149
例如,对于1、2、128、256,输出可以为(16位数字):
0000000000000001
0000000000000010
0000000010000000
0000000100000000

我尝试过

String.format("%16s", Integer.toBinaryString(1));

它会在左侧添加空格:

`               1'

如何使用0进行填充。我在Formatter文档中找不到相应的内容。还有其他方法吗?

P.S. 这篇文章介绍了如何在Java中使用左侧0填充格式化整数,但它并不适用于二进制表示。


你试过使用%016s吗? - Deniz Dogan
1
@Deniz 是的,它会失败并显示“Exception in thread "main" java.util.FormatFlagsConversionMismatchException: Conversion = s, Flags = 0”错误信息。 - khachik
看一下这个:https://dev59.com/NW855IYBdhLWcg3wNxgM#15124135 - fstang
17个回答

234

我认为这是一个次优解,但你可以这样做

String.format("%16s", Integer.toBinaryString(1)).replace(' ', '0')

3
好的,我现在这样做了,但我相信应该还有另一种方法 :) 谢谢。 - khachik
实际上经过一些研究,看起来你不能仅使用printf语法来做到这一点...所以也许情况并不那么糟糕。 - Samuel Parsonage
@Daniel 负数不会包含任何空格,所以它也是有效的。 - Eric
@Daniel Integer::toBinaryString doc: 返回整数参数的字符串表示形式,作为一个二进制无符号整数。 - Alan

20

在java.util.Formatter中没有二进制转换功能,我建议您使用String.replace来将空格字符替换为零,例如:

String.format("%16s", Integer.toBinaryString(1)).replace(" ", "0")
或者您可以按照此处提供的方法之一,实现将整数转换为带有左填充的二进制表示的逻辑。如果确实需要向格式化函数传递数字,您可以将二进制表示转换为BigInteger,然后在前面添加零,但这会在运行时非常昂贵。
String.format("%016d", new BigInteger(Integer.toBinaryString(1)))

谢谢,这个更好,因为它避免了在大数值(例如2^30)上的溢出。 - khachik
1
是的,但我真的不会这样做,我会使用replace方法或自己的填充方法:一种方法是再次使用String.format格式化所需填充长度和参数零,或者在代码中:String.format(“%0”+(32-binary.length())+“d”%s”,0,二进制)当然,您需要注意32-binary.length()的负面结果... - Zoran Regvart

17

这是对一个旧帖子的新回答。

要在二进制值前面填充特定长度的前导零,请尝试以下方法:

Integer.toBinaryString( (1 << len) | val ).substring( 1 )

如果 len = 4 并且 val = 1

Integer.toBinaryString( (1 << len) | val )

返回字符串"10001",然后

"10001".substring( 1 )

去掉了第一个字符。因此,我们得到了想要的:

"0001"

如果val可能是负数,最好尝试使用:

Integer.toBinaryString( (1 << len) | (val & ((1 << len) - 1)) ).substring( 1 )

简单而优雅。 - Jose Quinteiro

16
您可以使用Apache Commons StringUtils。它提供了用于填充字符串的方法:
StringUtils.leftPad(Integer.toBinaryString(1), 16, '0');

9

我尝试了许多我之前从未使用过的方法调用来使这个程序工作,它们有一定的成功率,直到我想到了一些如此简单的东西,以至于可能会起作用,结果真的起作用了!

我相信这个想法之前已经被想到过,不确定对于长串二进制代码是否有用,但对于16位字符串可以正常工作。希望对你有所帮助!(注意:第二段代码得到了改进)

String binString = Integer.toBinaryString(256);
  while (binString.length() < 16) {    //pad with 16 0's
        binString = "0" + binString;
  }

感谢Will的帮助,改进了这个答案使其在没有循环的情况下工作。虽然可能有些笨拙,但它有效,请尽可能改进并评论回来......
binString = Integer.toBinaryString(256);
int length = 16 - binString.length();
char[] padArray = new char[length];
Arrays.fill(padArray, '0');
String padString = new String(padArray);
binString = padString + binString;

这是一个不错且简单的解决方案。可以通过使用 binString.length() 和 16 之间的差异来创建一个字符串,然后将该字符串附加到 binString 中,而不是使用类似于此答案的循环:https://dev59.com/5XE85IYBdhLWcg3wYSZk#2804866 来改进它。 - Will
2
你真是太棒了,我现在就把这个加入我的代码!我也不喜欢那个循环,谢谢你!!! - Tom Spencer

6

用户user3608934的想法有一个更简单的版本:“这是一种旧技巧,创建一个包含16个0的字符串,然后附加您获得的修剪二进制字符串。”

private String toBinaryString32(int i) {
    String binaryWithOutLeading0 = Integer.toBinaryString(i);
    return "00000000000000000000000000000000"
            .substring(binaryWithOutLeading0.length())
            + binaryWithOutLeading0;
}

4

我不知道“正确”的解决方案,但我可以为您提供一个快速的补丁。

String.format("%16s", Integer.toBinaryString(1)).replace(" ", "0");

我刚刚试了一下,发现它能很好地工作。


为什么格式化程序只有16个字符宽?为什么不是%32s - ring bearer

4

从Java 11开始,您可以使用repeat(...)方法:

"0".repeat(Integer.numberOfLeadingZeros(i) - 16) + Integer.toBinaryString(i)

或者,如果您需要任何整数的32位表示:

"0".repeat(Integer.numberOfLeadingZeros(i != 0 ? i : 1)) + Integer.toBinaryString(i)

对于16位版本,是否也应该像32位版本一样检查i是否为零? - k314159

3

尝试...

String.format("%016d\n", Integer.parseInt(Integer.toBinaryString(256)));

我不认为这是做这件事的“正确”方式...但它有效 :)


1
这绝对是一种不好的方法,因为它只适用于输入值的一小部分......它能够成功产生的最大输出是0000001111111111,对于输入值1023。任何比这更大的值都将产生来自toBinaryString(1024)的输出10000000000,这对于parseInt(...)来说太大了。因此,该输入仅适用于64K个可能输入值中的1K个。 - rolfl

1
我会编写自己的工具类,其中包含以下方法。
public class NumberFormatUtils {

public static String longToBinString(long val) {
    char[] buffer = new char[64];
    Arrays.fill(buffer, '0');
    for (int i = 0; i < 64; ++i) {
        long mask = 1L << i;
        if ((val & mask) == mask) {
            buffer[63 - i] = '1';
        }
    }
    return new String(buffer);
}

public static void main(String... args) {
    long value = 0b0000000000000000000000000000000000000000000000000000000000000101L;
    System.out.println(value);
    System.out.println(Long.toBinaryString(value));
    System.out.println(NumberFormatUtils.longToBinString(value));
}

}

输出:

5
101
0000000000000000000000000000000000000000000000000000000000000101

相同的方法可以应用于任何整数类型。注意掩码的类型。

long mask = 1L << i;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接