user48956
user48956

Reputation: 15788

How to convert any a number to a long

Suppose I have:

val number:AnyVal

and I know x may be any number (for our purposes, a Float, Double, Int, Long).

What's the easiest way to convert such a number to a Long:

val l = number.toLong   //fails for AnyVal

Upvotes: 13

Views: 37481

Answers (4)

richj
richj

Reputation: 7529

Updated answer for Scala 2.11

My original answer does not work in newer versions of Scala because the implicit conversion to RichLong is no longer available.

This updated version works for numbers via type matching for Number sub-types and also for Strings via an implicit conversion in Scala 2.11:

object LongNumber {
  def cast(number: Any): Long = number match {
    case n: Number => n.longValue()
    case x         => throw new IllegalArgumentException(s"$x is not a number.")
  }

  // Test cases
  def main(args: Array[String]): Unit = {
    val twelveByte:     Byte   = 0x0c
    val twelveString:   String = "12"

    println(s"Converting a long:   ${cast(12L)}")
    println(s"Converting an int:   ${cast(12)}")
    println(s"Converting a double: ${cast(12.0)}")
    println(s"Converting a byte:   ${cast(twelveByte)}")
    println(s"Converting a string: $twelveString")
  }
}

The matching technique is a minor variation on the casting technique used in other answers.

Original answer for older versions of Scala

Attempting implicit conversion to RichLong in a match block seems to work quite nicely:

import scala.runtime.RichLong

...

  def cast(number: Any): Long = number match {
    case n: RichLong => n.toLong
    case x => throw new IllegalArgumentException(s"$x is not a number.")
  }

It might also be possible to add a case for matching a String in numeric format if you wanted to cater for that possibility.

Upvotes: 3

Randall Schulz
Randall Schulz

Reputation: 26486

How about:

scala> import scala.util.Try
import scala.util.Try

scala> val i1: Int = 23
i1: Int = 23

scala> val l1: Long = 42
l1: Long = 42

scala> val f1: Float = 14.9f
f1: Float = 14.9

scala> val d1: Double = 14.96
d1: Double = 14.96

scala> val b1: Boolean = true
b1: Boolean = true

scala> List(i1, l1, f1, d1, b1) map (x => Try(x.asInstanceOf[Number].longValue)) foreach (println(_))
Success(23)
Success(42)
Success(14)
Success(14)
Failure(java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Number)

scala> List(i1, l1, f1, d1, b1) map (x => Try(x.asInstanceOf[Number].longValue)) foreach (n => println(n.get))
23
42
14
14
java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.Number
    at $anonfun$1$$anonfun$apply$1.apply$mcJ$sp(<console>:14)
    at $anonfun$1$$anonfun$apply$1.apply(<console>:14)
    at $anonfun$1$$anonfun$apply$1.apply(<console>:14)
    at scala.util.Try$.apply(Try.scala:161)
    at $anonfun$1.apply(<console>:14)
    at $anonfun$1.apply(<console>:14)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
    at scala.collection.immutable.List.foreach(List.scala:318)
    at scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
    at scala.collection.AbstractTraversable.map(Traversable.scala:105)
    at .<init>(<console>:14)

Upvotes: 13

andy
andy

Reputation: 2993

You can cast it to a Number if you know it's definitely going to be a Float, Double, Int, or Long. Then you can call longValue:

val number:AnyVal = 10
val l:Long = number.asInstanceOf[Number].longValue

Upvotes: 22

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297155

If you don't have any information about the more specific type, then you'll have to pattern match against each option.

Upvotes: 1

Related Questions