【问题标题】:Spark decimal type precision lossSpark小数类型精度损失
【发布时间】:2019-03-07 14:43:27
【问题描述】:

我正在对货币度量的 spark 十进制类型进行一些测试,并且在设置比例和精度时看到了一些奇怪的精度结果,如下所示。我想确保在计算过程中不会丢失任何数据,但下面的示例并不能保证这一点。谁能告诉我为什么 spark sql 会发生这种情况?当前版本为 2.3.0

val sql = """select cast(cast(3 as decimal(38,14)) / cast(9 as decimal(38,14)) as decimal(38,14)) val"""
spark.sql(sql).show

返回

+----------------+
|             val|
+----------------+
|0.33333300000000|
+----------------+

【问题讨论】:

  • 您的 SQL 在 Spark 2.2.1 上运行良好,产生 0.3333... 和 14 3s。
  • 看起来有人为此创建了一张 JIRA 票证,并引用了这篇文章。谢谢。

标签: scala apache-spark apache-spark-sql


【解决方案1】:

这是一个当前未解决的问题,请参阅SPARK-27089。建议的解决方法是调整以下设置。我验证了 SQL 语句在将此设置设置为 false 的情况下按预期工作。

spark.sql.decimalOperations.allowPrecisionLoss=false

【讨论】:

    【解决方案2】:

    使用 BigDecimal 来避免精度损失。见Double vs. BigDecimal?

    示例:

    scala> val df = Seq(BigDecimal("0.03"),BigDecimal("8.20"),BigDecimal("0.02")).toDS
    df: org.apache.spark.sql.Dataset[scala.math.BigDecimal] = [value: decimal(38,18)]
    
    scala> df.select($"value").show
    +--------------------+
    |               value|
    +--------------------+
    |0.030000000000000000|
    |8.200000000000000000|
    |0.020000000000000000|
    +--------------------+
    

    使用 BigDecimal:

    scala> df.select($"value" + BigDecimal("0.1")).show
    +-------------------+
    |      (value + 0.1)|
    +-------------------+
    |0.13000000000000000|
    |8.30000000000000000|
    |0.12000000000000000|
    +-------------------+
    

    如果您不使用 BigDecimal,则会有精度损失。在这种情况下,0.1 是双精度数

    scala> df.select($"value" +  lit(0.1)).show
    +-------------------+
    |      (value + 0.1)|
    +-------------------+
    |               0.13|
    |  8.299999999999999|
    |0.12000000000000001|
    +-------------------+
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-15
      • 2014-07-13
      • 1970-01-01
      • 1970-01-01
      • 2019-01-01
      • 1970-01-01
      • 2019-05-11
      相关资源
      最近更新 更多