spark decimal(38,18)超出38限制的思考

总结一下
Java/Scala中的

  • scala.math.BigDecimal
  • scala.math.BigInt
  • java.math.BigDecimal
  • java.math.BigInteger
    Python中的
  • int
  • decimal.Decimal
    以上列出的数据类型,在内存允许的情况下作算术运算时是没有数值范围上限的

spark中的DecimalType就不一样了,参考源码:
val MAX_PRECISION = 38
val MAX_SCALE = 38
val SYSTEM_DEFAULT: DecimalType = DecimalType(MAX_PRECISION, 18)
val USER_DEFAULT: DecimalType = DecimalType(10, 0)

遇到的问题:
有一种需求,数值岂止是天文数字且要求保证精度(decimal(38,18))。沉默不语的DoubleType被喷了个狗血淋头(:
丢一个IEEE二进制浮点数算术标准(IEEE 754)可自行Google搜索研究
需求已经提出了,实现思路:
pyspark中对于浮点数值运算时,定义udf,在udf内部通过decimal进行计算,最终返回StringType或返回DecimalType(38,18)

# eval('%s * %s')
# eval('pow(%s,%s)')
# eval('%s + %s')
# eval函数使用参考https://www.programiz.com/python-programming/methods/built-in/eval
from decimal import *
decimalMaxvalue = Decimal('99999999999999999999.999999999999999999')

def calcByDecimal(x, y, myexpr):
    expr = myexpr % ("Decimal('" + str(x) + "')", "Decimal('" + str(y) + "')")
    result = eval(expr,{'Decimal': Decimal})
    if (result > decimalMaxvalue):
    # 可自行控制返回的decimal大小或者不控制大小即返回stringtype
        return decimalMaxvalue
    else:
        return result

# 或者

def calcByDecimal(list, myexpr):
    tup = ()
    for e in list:
        e = "Decimal('" + str(e) + "')"
        tup = tup + (e,)
    expr = myexpr % tup
    result = eval(expr,{'Decimal': Decimal})
    if (result > decimalMaxvalue):
        return decimalMaxvalue
    else:
        return result

# from pyspark.sql.types import DecimalType
# import pyspark.sql.functions as F
# from pyspark.sql.functions import udf
# myudf = udf(calcByDecimal, DecimalType(38, 18))
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值