在 Scala 中格式化二进制值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9442381/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Formatting binary values in Scala
提问by Hyman
Does Scala have a built in formatter for binary data?
Scala 有内置的二进制数据格式化程序吗?
For example to print out: 00000011 for the Int value 3.
例如打印出:00000011 表示 Int 值 3。
Writing one won't be difficult - just curious if it exists.
写一个并不难——只是好奇它是否存在。
回答by Lauri
scala> 3.toBinaryString
res0: String = 11
Scala has an implicit conversion from Int to RichInt which has a method toBinaryString. This function does not print the leading zeroes though.
Scala 有一个从 Int 到 RichInt 的隐式转换,它有一个 toBinaryString 方法。但是,此函数不打印前导零。
回答by Hosam Aly
I don't know of a direct API method to do it, but here is one way of doing it:
我不知道有什么直接的 API 方法可以做到这一点,但这是一种方法:
def toBinary(i: Int, digits: Int = 8) =
String.format("%" + digits + "s", i.toBinaryString).replace(' ', '0')
回答by user unknown
8 digits for number 3 with leading zeros:
带有前导零的数字 3 的 8 位数字:
printf ("%08d", 3.toBinaryString.toInt)
00000011
Since Hosam Aly suggests to create a String as well, here is a method to do so:
由于 Hosam Aly 也建议创建一个字符串,这里有一个方法:
def asNdigitBinary (source: Int, digits: Int): String = {
val l: java.lang.Long = source.toBinaryString.toLong
String.format ("%0" + digits + "d", l) }
In the general case, using a Long is more appropriate, since binary values get long very fast:
在一般情况下,使用 Long 更合适,因为二进制值会很快变长:
scala> asNdigitBinary (1024*512-1, 32)
res23: String = 00000000000001111111111111111111
So keep that in mind - a selfmade, recursive approach which generates digit by digit and fills them up in the end would be easily made to handle arbitrary values of BigInt.
所以请记住这一点——一种自制的、逐位生成并在最后填充它们的递归方法很容易处理 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
}
It would be nice, if
就好了,如果
def asNdigitBinary (source: Int, digits: Int): String = {
val l = BigInt (source.toBinaryString.toLong)
String.format ("%0" + digits + "d", l)}
would work, but "%0Nd" does not match for BigInt digits. Maybe a Bugreport/Feature request should be made? But to Scala or Java?
会工作,但“%0Nd”与 BigInt 数字不匹配。也许应该提出错误报告/功能请求?但是对于 Scala 或 Java?
回答by Niklas Hallqvist
I usually use to prepend zeroes of the wanted length -1 and then just chop the rightmost characters:
我通常用来在想要的长度 -1 前面加上零,然后只截断最右边的字符:
"0000000" + 3.toBinaryString takeRight 8
This works fine for negative values as well.
这也适用于负值。
回答by om-nom-nom
Here is one more way (old Java):
这是另一种方式(旧Java):
val x = 5
val str = Integer.toString(x,2)
Just like Lauri answer, it doesn't print leading zeros.
就像劳里的回答一样,它不打印前导零。
回答by chaotic3quilibrium
The Scala standard library's built-in to-binary-digits Stringformatters (toBinaryString) for the integer types (Byte, Short, Char, Int, and Long) are very limited. And an implementation for Booleanisn't provided.
斯卡拉标准库的内置到二进制位数String格式化(toBinaryString)为整数类型(Byte,Short,Char,Int,和Long)是非常有限的。并且Boolean没有提供for 的实现。
Additionally, for Byteand Short, the actual emitted format is wrong for negative values (as both forward to the Int.toBinaryStringimplementation which then 1fills out to 32 characters, not the correct widths of 8 and 16 characters respectively).
此外,对于Byte和Short,实际发出的格式对于负值是错误的(因为两者都转发到Int.toBinaryString实现,然后1填充到 32 个字符,而不是分别为 8 和 16 个字符的正确宽度)。
Also, I have read through every answer here. And I learned quite a bit about the various ways to approach solving this problem. Ultimately, though, there wasn't a drop in solution which "just worked" within my current project. So...
另外,我已经通读了这里的每个答案。我学到了很多关于解决这个问题的各种方法。但是,最终,在我当前的项目中“刚刚工作”的解决方案并没有下降。所以...
I have created a single method implementation fixing and then enhancing all of the above inconsistencies, errors, and adds missing functionality. Now, if I could only figure out how to get this included in the Standard Library for 2.13 and Scala 3...
我创建了一个单一的方法实现修复,然后增强了上述所有的不一致、错误,并添加了缺失的功能。现在,如果我只能弄清楚如何将它包含在 2.13 和 Scala 3 的标准库中......
The sizeparameter has three domains of values. See the code comments for more precise details.
该size参数具有三个值域。有关更精确的详细信息,请参阅代码注释。
size = 0-> (DEFAULT) zero fill to the bit size of the containing typesize < 0-> model the default behavior of toBinaryString function already onByte,Short,Char,Int, andLong- also fix the hidden upcast toIntfor bothByteandShortsize > 0-> caller designated zero fill - ignored if the size is smaller than the length required to capture the1digit immediately to the left of the leftmost0digit (to preserve the sign)
size = 0-> (DEFAULT) 零填充到包含类型的位大小size < 0- >已经在模拟toBinaryString功能的默认行为Byte,Short,Char,Int,和Long-也解决了隐藏上溯造型到Int两个Byte及Shortsize > 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)
)
}
回答by radumanolescu
This will print the leading zeroes:
这将打印前导零:
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)
}
回答by jxstanford
You can do something like this:
你可以这样做:
scala> val x = 3
x: Int = 3
scala> Integer.toString(x, 2)
res4: java.lang.String = 11
As with other suggestions, this doesn't have leading zeros...
与其他建议一样,这没有前导零......

