Round 函数

round()

ROUND 数字函数按指定的位数对提供的值进行舍入。

RoundingMode
  • ROUND_UP 向远离零的方向舍入。 总是在非零的舍弃尾数前面增大数字。 这种舍入方式从不会缩小计算结果的绝对

  • ROUND_DOWN
    向零方向舍入。 从不在舍弃的尾数前面增大数字,即截断。 这种舍入方式从不会增大计算结果的绝对值。

  • ROUND_CEILING 向正无穷大方向舍入。 如果小数为正,将按照 ROUND_UP 方式舍入;如果小数为负,将按照ROUND_DOWN 方式舍入。 这种舍入方式从不会缩小计算出的值。

  • ROUND_FLOOR 向负无穷大方向舍入。 如果小数为正,将按照 ROUND_DOWN方式舍入;如果小数为负,将按照 ROUND_UP方式舍入。 这种舍入方式从不会增大计算出的值。

  • ROUND_HALF_UP 向“最接近的数字”舍入,只有在与两个相邻数字距离相等的情况下才按照 ROUND_UP 方式舍入。如果舍弃的尾数 >= 0.5,将按照ROUND_UP 方式舍入;否则按照 ROUND_DOWN 方式舍入。 这种舍入方式就是学校里通常讲的四舍五入。

  • ROUND_HALF_DOWN 向“最接近的数字”舍入,只有在与两个相邻数字距离相等的情况下才按照 ROUND_DOWN 方式舍入。 如果舍弃的尾数 > 0.5,将按照 ROUND_UP 方式舍入;否则按照 ROUND_DOWN 方式舍入。

  • ROUND_HALF_EVEN 向“最接近的数字”舍入,只有在与两个相邻数字的距离相等的情况下才向相邻的偶数舍入。如果被舍弃尾数左边的数字为奇数,将按照 ROUND_HALF_UP 方式舍入;如果为偶数,将按照 ROUND_HALF_DOWN方式舍入。在反复进行一系列计算时,这种舍入方式可以将累积误差减到最小。这种舍入方式有时也称为“银行家舍入法”。

默认方式 ROUND_HALF_EVEN

如果未指定 方式,那么将使用值 ROUND_HALF_EVEN。

Spark round 函数

https://spark.apache.org/docs/latest/api/sql/index.html#round

abstract class RoundBase(child: Expression, scale: Expression,
    mode: BigDecimal.RoundingMode.Value, modeStr: String)
  extends BinaryExpression with Serializable with ImplicitCastInputTypes with SupportQueryContext {
...

  override lazy val dataType: DataType = child.dataType match {
    case DecimalType.Fixed(p, s) =>
      // After rounding we may need one more digit in the integral part,
      // e.g. `ceil(9.9, 0)` -> `10`, `ceil(99, -1)` -> `100`.
      val integralLeastNumDigits = p - s + 1
      if (_scale < 0) {
        // negative scale means we need to adjust `-scale` number of digits before the decimal
        // point, which means we need at lease `-scale + 1` digits (after rounding).
        val newPrecision = math.max(integralLeastNumDigits, -_scale + 1)
        // We have to accept the risk of overflow as we can't exceed the max precision.
        DecimalType(math.min(newPrecision, DecimalType.MAX_PRECISION), 0)
      } else {
        val newScale = math.min(s, _scale)
        // We have to accept the risk of overflow as we can't exceed the max precision.
        DecimalType(math.min(integralLeastNumDigits + newScale, 38), newScale)
      }
    case t => t
  }
  // not overriding since _scale is a constant int at runtime
  def nullSafeEval(input1: Any): Any = {
    dataType match {
      case DecimalType.Fixed(p, s) =>
        val decimal = input1.asInstanceOf[Decimal]
        if (_scale >= 0) {
          // Overflow cannot happen, so no need to control nullOnOverflow
          decimal.toPrecision(decimal.precision, s, mode)
        } else {
          Decimal(decimal.toBigDecimal.setScale(_scale, mode), p, s)
        }
      case ByteType if ansiEnabled =>
        MathUtils.withOverflow(
          f = BigDecimal(input1.asInstanceOf[Byte]).setScale(_scale, mode).toByteExact,
          context = getContextOrNull)
      case ByteType =>
        BigDecimal(input1.asInstanceOf[Byte]).setScale(_scale, mode).toByte
      case ShortType if ansiEnabled =>
        MathUtils.withOverflow(
          f = BigDecimal(input1.asInstanceOf[Short]).setScale(_scale, mode).toShortExact,
          context = getContextOrNull)
      case ShortType =>
        BigDecimal(input1.asInstanceOf[Short]).setScale(_scale, mode).toShort
      case IntegerType if ansiEnabled =>
        MathUtils.withOverflow(
          f = BigDecimal(input1.asInstanceOf[Int]).setScale(_scale, mode).toIntExact,
          context = getContextOrNull)
      case IntegerType =>
        BigDecimal(input1.asInstanceOf[Int]).setScale(_scale, mode).toInt
      case LongType if ansiEnabled =>
        MathUtils.withOverflow(
          f = BigDecimal(input1.asInstanceOf[Long]).setScale(_scale, mode).toLongExact,
          context = getContextOrNull)
      case LongType =>
        BigDecimal(input1.asInstanceOf[Long]).setScale(_scale, mode).toLong
      case FloatType =>
        val f = input1.asInstanceOf[Float]
        if (f.isNaN || f.isInfinite) {
          f
        } else {
          BigDecimal(f.toDouble).setScale(_scale, mode).toFloat
        }
      case DoubleType =>
        val d = input1.asInstanceOf[Double]
        if (d.isNaN || d.isInfinite) {
          d
        } else {
          BigDecimal(d).setScale(_scale, mode).toDouble
        }
    }
  }
  /** Constructs a `BigDecimal` whose value is equal to that of the
   *  specified double value.  Equivalent to `BigDecimal.decimal`.
   *
   *  @param d the specified `Double` value
   *  @return  the constructed `BigDecimal`
   */
  def apply(d: Double): BigDecimal = decimal(d, defaultMathContext)
val defaultMathContext = MathContext.DECIMAL128
    /**
     *  A {@code MathContext} object with a precision setting
     *  matching the IEEE 754R Decimal128 format, 34 digits, and a
     *  rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
     *  IEEE 754R default.
     */
    public static final MathContext DECIMAL128 =
        new MathContext(34, RoundingMode.HALF_EVEN);
  • DecimalType(precision: Int, scale: Int)
/**
 * The data type representing `java.math.BigDecimal` values.
 * A Decimal that must have fixed precision (the maximum number of digits) and scale (the number
 * of digits on right side of dot).
 *
 * The precision can be up to 38, scale can also be up to 38 (less or equal to precision).
 *
 * The default precision and scale is (10, 0).
 *
 * Please use `DataTypes.createDecimalType()` to create a specific instance.
 *
 * @since 1.3.0
 */
@Stable
case class DecimalType(precision: Int, scale: Int) extends FractionalType {

  DecimalType.checkNegativeScale(scale)

  if (scale > precision) {
    throw DataTypeErrors.decimalCannotGreaterThanPrecisionError(scale, precision)
  }

  if (precision > DecimalType.MAX_PRECISION) {
    throw DataTypeErrors.decimalPrecisionExceedsMaxPrecisionError(
      precision, DecimalType.MAX_PRECISION)
  }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhixingheyi_tian

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值