在Scala中格式化二进制值

时间:2012-02-25 08:00:23

标签: scala string-formatting

Scala是否有内置的二进制数据格式化程序?

例如打印输出:00000011表示Int值3。

写一个并不困难 - 只是好奇它是否存在。

8 个答案:

答案 0 :(得分:60)

scala> 3.toBinaryString
res0: String = 11

Scala有一个从Int到RichInt的隐式转换,它有一个方法toBinaryString。此功能不会打印前导零。

答案 1 :(得分:20)

我不知道有直接的API方法,但这是一种方法:

def toBinary(i: Int, digits: Int = 8) =
    String.format("%" + digits + "s", i.toBinaryString).replace(' ', '0')

答案 2 :(得分:10)

带有前导零的数字3的8位数字:

printf ("%08d", 3.toBinaryString.toInt)
00000011

由于Hosam Aly建议也创建一个String,这是一个方法:

def asNdigitBinary (source: Int, digits: Int): String = {
  val l: java.lang.Long = source.toBinaryString.toLong
  String.format ("%0" + digits + "d", l) }

在一般情况下,使用Long更合适,因为二进制值变得非常快:

scala> asNdigitBinary (1024*512-1, 32)
res23: String = 00000000000001111111111111111111

因此请记住这一点 - 一种自制的,递归的方法,它可以逐位生成并最终填充它们,可以很容易地处理BigInt的任意值。

def toBinDigits (bi: BigInt): String = { 
  if (bi == 0) "0" else toBinDigits (bi /2) + (bi % 2)}

def fillBinary (bi: BigInt, len: Int) = { 
  val s = toBinDigits (bi)
  if (s.length >= len) s 
  else (List.fill (len-s.length) ("0")).mkString ("") + s
}

如果

那就太好了
def asNdigitBinary (source: Int, digits: Int): String = {
  val l = BigInt (source.toBinaryString.toLong) 
  String.format ("%0" + digits + "d", l)}

会起作用,但“%0Nd”与BigInt数字不匹配。也许应该提出Bugreport / Feature请求?但是对于Scala还是Java?

答案 3 :(得分:3)

这是另一种方式(旧Java):

val x = 5
val str = Integer.toString(x,2)

就像Lauri的回答一样,它不会打印前导零。

答案 4 :(得分:3)

我通常使用前置所需长度为-1的零,然后只删除最右边的字符:

"0000000" + 3.toBinaryString takeRight 8

这也适用于负值。

答案 5 :(得分:2)

Scala标准库针对整数类型(StringtoBinaryStringByte的内置二进制数字Short格式器(Char) ,IntLong)非常有限。并且没有提供Boolean的实现。

另外,对于ByteShort,对于负值,实际发出的格式是错误的(因为两者都转发给Int.toBinaryString实现,然后1填充为32字符,而不是正确的8和16个字符的宽度。

此外,我在这里已经阅读了所有答案。而且我学到了很多解决该问题的方法。最终,尽管如此,在我当前的项目中并没有出现“可以正常使用”的解决方案。所以...

我创建了一个方法实现,修复并增强了上述所有不一致之处,错误,并增加了缺少的功能。现在,如果我只能弄清楚如何将其包含在2.13和Scala 3的标准库中……

size参数具有三个值域。有关更精确的信息,请参见代码注释。

  1. size = 0->(默认)零填充到包含类型的位大小
  2. size < 0->对toBinaryString函数在ByteShortCharIntLong上的默认行为进行建模-还可以将IntByte的隐藏上流都固定为Short
  3. size > 0->呼叫者指定为零填充-如果大小小于捕获最左边的1位左侧的0位所需的长度,则忽略(保留)标志)

    def toBinaryString[A <: AnyVal](value: A, size: Int = 0): String = {
      val zerosX64: String = //maximum possible number of leading zeros
        "0" * 64

      val (valueAsBinaryString, typeSize) =
        value match {
          case valueAlmostTyped: Boolean =>
            (if (valueAlmostTyped) "1" else "0", 1)
          case valueAlmostTyped: Byte =>
            (valueAlmostTyped.toByte.toBinaryString.takeRight(8), 8) //take() fixes hidden upcast to Int in Byte.toBinaryString
          case valueAlmostTyped: Short =>
            (valueAlmostTyped.toShort.toBinaryString.takeRight(16), 16) //take() fixes hidden upcast to Int in Short.toBinaryString
          case valueAlmostTyped: Char =>
            (valueAlmostTyped.toChar.toBinaryString, 16)
          case valueAlmostTyped: Int =>
            (valueAlmostTyped.toInt.toBinaryString, 32)
          case valueAlmostTyped: Long =>
            (valueAlmostTyped.toLong.toBinaryString, 64)
          case _ =>
            throw new IllegalArgumentException(s"toBinaryString not implemented for this type [${value.getClass.getSimpleName}] - only implemented for Boolean, Byte, Short, Char, Int, and Long")
        }

      val newSize =
        if (size < 0) //model and fix the behavior of existing toBinaryString function on Byte, Short, Char, Int, and Long, and add for Binary
          valueAsBinaryString.length
        else
          if (size == 0) //zero fill to the bit size of the containing type
            typeSize
          else
            if (valueAsBinaryString.length > size) //possibly override the caller specified custom size value as it is smaller than the resulting valueAsBinaryString itself
              if (valueAsBinaryString.take(valueAsBinaryString.length - size + 1).exists(_ == '0')) //only override if there isn't a zero dropped (which includes protecting the sign by ensuring if all 1s preceded the 0, at least a single one is preserved
                valueAsBinaryString.length
              else //caller specified custom value
                size
            else //caller specified custom value
              size
      ( (
            if (newSize > valueAsBinaryString.length)
              zerosX64.take(newSize - valueAsBinaryString.length)
            else
              ""
        )
        + valueAsBinaryString.takeRight(newSize)
      )
    }

答案 6 :(得分:1)

这将打印前导零:

  def int2bin(i: Int, numPos: Int): String = {
    def nextPow2(i: Int, acc: Int): Int = if (i < acc) acc else nextPow2(i, 2 * acc)
    (nextPow2(i, math.pow(2,numPos).toInt)+i).toBinaryString.substring(1)
  }

答案 7 :(得分:0)

您可以这样做:

scala> val x = 3
x: Int = 3

scala> Integer.toString(x, 2)
res4: java.lang.String = 11

与其他建议一样,这没有前导零......