Scala: How to parse a number from a String

Scala FAQ: How do I parse a number (Int, Long, Float, BigInt, BigDecimal, etc.) from a String in Scala?

Solution

You can parse numbers from strings in Scala by using the to* methods that are available on a String (courtesy of the Scala StringLike trait):

scala> "100".toInt
res0: Int = 100

scala> "100".toDouble
res1: Double = 100.0

scala> "100".toFloat
res2: Float = 100.0

scala> "1".toLong
res3: Long = 1

scala> "1".toShort
res4: Short = 1

scala> "1".toByte
res5: Byte = 1

But be careful, because these methods can throw the usual Java NumberFormatException:

scala> "foo".toInt 
java.lang.NumberFormatException: For input string: "foo" 
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java) 
    at java.lang.Integer.parseInt(Integer.java:449) 
    ... more output here ...

BigInt and BigDecimal

Like the other numeric types, BigInt and BigDecimal instances can also be created directly from strings (and can also throw a NumberFormatException):

scala> val b = BigInt("1")
b: scala.math.BigInt = 1

scala> val b = BigDecimal("3.14159")
b: scala.math.BigDecimal = 3.14159

Handling a base and radix

If you need to perform calculations using bases other than 10, you’ll find the toInt method in the Scala Int class doesn’t have a method that lets you pass in a base and radix. To solve this problem, use the parseInt method in the java.lang.Integer class, as shown in these examples:

scala> Integer.parseInt("1", 2)
res0: Int = 1

scala> Integer.parseInt("10", 2)
res1: Int = 2

scala> Integer.parseInt("100", 2)
res2: Int = 4

scala> Integer.parseInt("1", 8)
res3: Int = 1

scala> Integer.parseInt("10", 8)
res4: Int = 8

Using implicit conversions

If you’re a fan of implicit conversions, you can create an implicit class and method to help solve the problem. As described in Recipe 1.10 of the Scala Cookbook, “Add Your Own Methods to the String Class” and My Scala 2.10 implicit class example, create the implicit conversion as follows:

implicit class StringToInt(s: String) {
    def toInt(radix: Int) = Integer.parseInt(s, radix)
}

Defining this implicit class (and bringing it into scope) adds a toInt method that takes a radix argument to the String class, which you can now call instead of calling Integer.parseInt:

scala> implicit class StringToInt(s: String) {
     |     def toInt(radix: Int) = Integer.parseInt(s, radix)
     | }
defined class StringToInt

scala> "1".toInt(2)
res0: Int = 1

scala> "10".toInt(2)
res1: Int = 2

scala> "100".toInt(2)
res2: Int = 4

scala> "100".toInt(8)
res3: Int = 64

scala> "100".toInt(16)
res4: Int = 256

See my implicit class tutorial for more details on how to implement this solution outside of the REPL.

Discussion

If you’ve used Java to convert a String to a numeric data type, the NumberFormatException is familiar. However, Scala doesn’t have checked exceptions, so you’ll probably want to handle this situation differently.

First, you don’t have to declare that Scala methods can throw an exception, so it’s perfectly legal to declare a Scala method like this:

// not required to declare "throws NumberFormatException"
def toInt(s: String) = s.toInt

If you’re going to allow an exception to be thrown like this, callers of your method might appreciate knowing that this can happen. Consider adding a Scaladoc comment to your method in this case.

If you prefer to declare that your method can throw an exception, mark it with the @throws annotation, as shown here:

@throws(classOf[NumberFormatException])
def toInt(s: String) = s.toInt

This approach is required if the method will be called from Java code, as described in Recipe 17.2 of the Scala Cookbook, “Add Exception Annotations to Scala Methods to Work with Java”.

However, in Scala, situations like this are often handled with the Option/Some/None pattern, as described in Recipe 20.6 of the Cookbook, “Using the Option/Some/None Pattern.” With this approach, define the toInt method like this:

def toInt(s: String):Option[Int] = {
    try {
        Some(s.toInt)
    } catch {
        case e: NumberFormatException => None
    }
}

Now you can call the toInt method in several different ways, depending on your needs. One way is with getOrElse:

println(toInt("1").getOrElse(0))   // 1
println(toInt("a").getOrElse(0))   // 0

// assign the result to x
val x = toInt(aString).getOrElse(0)

Another approach -- the preferred approach -- is to use a match expression. You can write a match expression to print the toInt result like this:

toInt(aString) match {
    case Some(n) => println(n)
    case None => println("Boom! That wasn't a number.")
}

You can also write a match expression as follows to assign the result to a variable:

val result = toInt(aString) match {
    case Some(x) => x
    case None => 0  // however you want to handle this
}

If these examples haven’t yet sold you on the Option/Some/None approach, you’ll see in Chapter 10 and Chapter 11 of the Cookbook that this pattern is incredibly helpful and convenient when working with collections.

Alternatives to using Option

If you like the Option/Some/None concept, but need access to the exception information, there are several additional possibilities:

  • Try, Success, and Failure (introduced in Scala 2.10)
  • Either, Left, and Right

These alternate approaches are discussed in Recipe 20.6 of the Cookbook, “Using the Option/Some/None Pattern”. (The new Try/Success/Failure approach is especially appealing.)