Scala 如何将任意数字转换为长数字

Scala 如何将任意数字转换为长数字,scala,type-conversion,Scala,Type Conversion,假设我有: val number:AnyVal 我知道x可以是任何数字(为了我们的目的,一个浮点数,Double,Int,Long) 将这样的数字转换为长数字的最简单方法是什么: val l = number.toLong //fails for AnyVal 如果您没有关于更具体类型的任何信息,则必须对每个选项进行模式匹配。如果您知道它肯定是浮点、双精度、整型或长型,则可以将其转换为数字。然后您可以调用longValue: val number:AnyVal = 10 val l:Lo

假设我有:

val number:AnyVal
我知道x可以是任何数字(为了我们的目的,一个浮点数,Double,Int,Long)

将这样的数字转换为长数字的最简单方法是什么:

val l = number.toLong   //fails for AnyVal

如果您没有关于更具体类型的任何信息,则必须对每个选项进行模式匹配。

如果您知道它肯定是浮点、双精度、整型或长型,则可以将其转换为数字。然后您可以调用longValue:

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

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)
scala>导入scala.util.Try
导入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:浮动=14.9
scala>val d1:Double=14.96
d1:Double=14.96
scala>val b1:Boolean=true
b1:布尔值=真
scala>List(i1、l1、f1、d1、b1)映射(x=>Try(x.asInstanceOf[Number].longValue))foreach(println(u1;))
成功(23)
成功(42)
成功(14)
成功(14)
失败(java.lang.ClassCastException:java.lang.Boolean无法转换为java.lang.Number)
scala>List(i1,l1,f1,d1,b1)映射(x=>Try(x.asInstanceOf[Number].longValue))foreach(n=>println(n.get))
23
42
14
14
java.lang.ClassCastException:java.lang.Boolean不能转换为java.lang.Number
在$anonfun$1$$anonfun$apply$1.apply$mcJ$sp(:14)
在$anonfun$1$$anonfun$apply$1。apply(:14)
在$anonfun$1$$anonfun$apply$1。apply(:14)
在scala.util.Try$.apply处(Try.scala:161)
在$anonfun$1.申请(:14)
在$anonfun$1.申请(:14)
位于scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
位于scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:244)
位于scala.collection.immutable.List.foreach(List.scala:318)
位于scala.collection.TraversableLike$class.map(TraversableLike.scala:244)
位于scala.collection.AbstractTraversable.map(Traversable.scala:105)
在。(:14)

Scala 2.11的更新答案

我最初的答案在较新版本的Scala中不起作用,因为到RichLong的隐式转换不再可用

此更新版本通过数字子类型的类型匹配适用于数字,也通过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")
  }
}
匹配技术是其他答案中使用的铸造技术的一个小变化

旧版本Scala的原始答案

尝试在匹配块中隐式转换为RichLong似乎效果很好:

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.")
  }

如果您想满足这种可能性,也可以添加一个匹配数字格式字符串的案例。

整洁-我从来没有想到自动装箱会正确-一定要记住。但是我们如何更改编号的类型?针对Scala 2.11进行了更新。