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.)
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |