1

有人可以向我解释一下吗:

scala> import spray.json._

import spray.json._



scala> import DefaultJsonProtocol._

import DefaultJsonProtocol._


scala> def check(n: BigDecimal) = {

     |     println(s"n.isValidByte = ${n.isValidByte}")

     |     println(s"n.isValidChar = ${n.isValidChar}")

     |     println(s"n.isValidDouble = ${n.isValidDouble}")

     |     println(s"n.isValidFloat = ${n.isValidFloat}")

     |     println(s"n.isValidInt = ${n.isValidInt}")

     |     println(s"n.isValidLong = ${n.isValidLong}")

     |     println(s"n.isValidShort = ${n.isValidShort}")

     | }

check: (n: BigDecimal)Unit

scala> check(JsNumber(0.16) match { case JsNumber(x) => x})

n.isValidByte = false

n.isValidChar = false

n.isValidDouble = false

n.isValidFloat = false

n.isValidInt = false

n.isValidLong = false

n.isValidShort = false

我正在使用带有 Scala 2.10.3 的 spray-json 1.2.6,这些是我的 libraryDependencies:

“io.spray” %% “spray-json” % “1.2.6”

谢谢,格雷加

4

1 回答 1

0

问题是从 BigDecimal 到 float 的转换并不完美,因此它返回 false。floatValue 必须进行一些舍入。观察:

BigDecimal(.16).floatValue                      //> res8: Float = 0.16

但是当您尝试转换 BigDecimal -> Float -> BigDecimal 时,您会看到舍入错误:

BigDecimal(BigDecimal(.16).floatValue)          //> res8: scala.math.BigDecimal = 0.1599999964237213

如果您选择了一个可以用 2 的幂精确表示的不同值,那么您的检查功能将起作用:

  BigDecimal(BigDecimal(.5).floatValue)           //> res10: scala.math.BigDecimal = 0.5
  BigDecimal(.5).isValidFloat                     //> res11: Boolean = true

TLDR BigDecimal 可以很好地处理任意小数,float 存储在 2 的幂中,因此它可以做的最好的不是 0.16,而是非常接近 0.1599999964237213,但由于存在一些损失,isValidFloat 返回 false。

于 2014-06-12T16:39:45.840 回答