How to write binary literals in Scala?
Asked Answered
G

8

30

Scala has direct support for using hex and octal numbers:

scala> 01267 + 0100
res1: Int = 759

scala> 0x12AF + 0x100
res2: Int = 5039

but how do you do express an integer as a binary number in Scala ?.

Georgianngeorgianna answered 25/8, 2011 at 21:1 Comment(1)
Note that as of 2.10, the use of a leading 0 to mean octal is deprecated.Xylia
K
33

If performance is not an issue, you can use a String and convert it to an integer.

val x = Integer.parseInt("01010101", 2)

Binary numbers aren't supported directly in part because you can easily convert from hexadecimal to binary and vice versa. To make your code clearer, you can put the binary number in a comment.

val x = 0x55 //01010101
Karissakarita answered 25/8, 2011 at 21:19 Comment(2)
Wow, that sucks. I don't agree with the justification that "you can easily convert from hexadecimal to binary and vice versa". If what you want is to use binary notation I think you should be able to, especially because Java supports it =(Angloindian
Your recipe does not work for me val x : Int = -2147483648 followed by val y : Int = Integer.parseInt(x.toBinaryString, 2) yields an exception. Notice that x is still a valid integer number.Ultan
S
20

In 2.10 you can create a string interpolator for that, e.g. it's possible to write b"0010" to mean 2. Using macros you can get rid of associated runtime overhead and do the conversion at compile-time. Take a look at Jason Zaugg's macrocosm to see it in action:

scala> b"101010"
res4: Int = 42

scala> b"102"
<console>:11: error: exception during macro expansion: invalid binary literal
              b"102"
              ^
Spatial answered 2/2, 2013 at 11:32 Comment(0)
X
9

Using the new "implicit class" and "value class" mechanisms in 2.10, you can write something like this to add convenience methods without the overhead of object creation:

implicit class IntToBase( val digits:String ) extends AnyVal {
  def base(b:Int) = Integer.parseInt( digits, b )
  def b = base(2)
  def o = base(8)
  def x = base(16)
}

That allows you to do things like

"555".o  // 365 decimal

and no IntToBase object is ever actually created.

Xylia answered 1/2, 2013 at 9:2 Comment(2)
This doesn't handle negative numbers in two's complement: "11111111111111111111111111111111".b => java.lang.NumberFormatException: For input string: "11111111111111111111111111111111"Seasick
Yes, parseInt() considers a leading "-" the indicator that you mean a negative number. The number you specified doesn't have that, so parseInt() thinks you mean the positive number, which is too large to be a 32-bit signed integer -- hence the exception. parseInt() does not consider a 1 in the high-order bit position to be an indicator that you mean a negative number (which would be a machine-dependent interpretation anyway).Xylia
I
6

You would need to be careful if you're converting from an integer that "looks like" binary as @agilesteel suggests. For example 0101.b would try to convert 65 decimal to binary (initial 0 signifying octal), whereas 101.b would try to convert 101 decimal to binary. It only really makes sense to try to convert from a String, for which there is Integer.parseInt, and from a number to the binary String representation, for which there is Integer.toString(x, 2).

I can't think of too many use-cases for programmatic binary literals. That said, they've made it to Java 7 as a number with prefix 0b, so I'd be surprised if they didn't appear in Scala soon. Java seems to have done fine without them for 15 years though.

Indictment answered 26/8, 2011 at 0:21 Comment(1)
Java has done "fine" without unsigned chars or decent bitwise operators too. By "fine", I mean people just give up on writing stuff that needs that in Java, or else suffer cursing Java every inch of the way.Nunuance
S
4

If you are planning on using it a lot you can simulate the behavior with an implicit conversion.

object Extensions {
  implicit def conversion(x: Int) = new BinaryInt(x)
  class BinaryInt(x: Int) {
    def b = {
      // Conversion code like Integer.parseInt
      // as Kim suggested
    }
  }
}

Now you can do stuff like

import Extensions._
val x = 0101.b
// or
val x = 5.b

You have to decide for yourself, which direction the conversion should go.

Slapdash answered 25/8, 2011 at 21:52 Comment(2)
Be careful: 0101 is an octal number!Upturn
It was till 2.10. See the other comments.Incubator
S
2

If you want to get a string of the binary representation of an Int you can call 4.toBinaryString. Padding is more difficult. You'll have to do something like: 4.toBinaryString.reverse.padTo(8, "0").reverse.mkString

Stun answered 24/3, 2017 at 13:49 Comment(0)
P
2

More than a decade later, Scala 2.13.13 supports binary literals using 0b10101 syntax.

https://github.com/scala/scala/releases/tag/v2.13.13

Painterly answered 1/3 at 12:23 Comment(1)
This needs to be the accepted answer. Take my upvote as a start.Magellan
M
0
def _0b(row: Int): Int = {
  row.toString
    .reverse
    .split("")
    .zipWithIndex
    .map(x => (x._1.toInt, x._2))
    .filter(_._1 == 1)
    .map(x => Math.pow(2,x._2).toInt)
    .sum
}

_0b(10011001) = 153

Though it is limited to 32Bit Values

Magritte answered 7/3, 2019 at 9:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.