我有以下四种方法,使用BigDecimal来舍入数字:
private def round(input: Byte, scale: Int): Byte = {
BigDecimal(input).setScale(scale, RoundingMode.HALF_UP).byteValue()
}
private def round(input: Short, scale: Int): Short = {
BigDecimal(input).setScale(scale, RoundingMode.HALF_UP).shortValue()
}
private def round(input: Int, scale: Int): Int = {
BigDecimal(input).setScale(scale, RoundingMode.HALF_UP).intValue()
}
private def round(input: Long, scale: Int): Long = {
BigDecimal(input).setScale(scale, RoundingMode.HALF_UP).longValue()
}
并计划将其概括为一轮:
private def round[T](input: Any, scale: Int, f: (BigDecimal) => T): T = {
f(BigDecimal(input.asInstanceOf[T]).setScale(scale, RoundingMode.HALF_UP))
}
并像这样使用这一轮:
round[Byte](b, scale, _.byteValue)
round[Short](s, scale, _.shortValue)
但上述广义round
无效,因为BigDecimal.apply
无法应用于T
,我该怎么办?
答案 0 :(得分:5)
您可以使用Numeric
类型
def round[T](input: T, scale: Int, f: BigDecimal => T)(implicit n: Numeric[T]): T = {
f(BigDecimal(n.toDouble(input)).setScale(scale, RoundingMode.HALF_UP))
}
可以用作:
round(5.525, 2, _.doubleValue)
res0: Double = 5.53
round(123456789L, -5, _.longValue)
res1: Long = 123500000
另一种方法可能是创建一个BigDecimalConverter
类型的类,这不是简洁但解决了转换为Double
的问题(这不是一个好主意一个通用函数,如RégisJean-Gilles在下面评论过。)
使用fromBigDecimal
方法更新以清理round
功能(感谢RégisJean-Gilles)。
trait BigDecimalConverter[T] {
def toBigDecimal(in: T) : BigDecimal
def fromBigDecimal(bd: BigDecimal) : T
}
object BigDecimalConverter {
implicit object IntToBigDecimal extends BigDecimalConverter[Int] {
def toBigDecimal(in: Int) = BigDecimal(in)
def fromBigDecimal(bd: BigDecimal) = bd.toInt
}
implicit object DoubleToBigDecimal extends BigDecimalConverter[Double] {
def toBigDecimal(in: Double) = BigDecimal(in)
def fromBigDecimal(bd: BigDecimal) = bd.toDouble
}
implicit object LongToBigDecimal extends BigDecimalConverter[Long] {
def toBigDecimal(in: Long) = BigDecimal(in)
def fromBigDecimal(bd: BigDecimal) = bd.toLong
}
implicit object BigDecimalToBigDecimal extends BigDecimalConverter[BigDecimal] {
def toBigDecimal(in: BigDecimal) = in
def fromBigDecimal(bd: BigDecimal) = bd
}
}
def round[T](input: T, scale: Int)(implicit bdc: BigDecimalConverter[T]): T =
bdc.fromBigDecimal(
bdc.toBigDecimal(input).setScale(scale, BigDecimal.RoundingMode.HALF_UP)
)
哪些可以与Double
,Long
,BigDecimal
,...正确使用:
round(10, 1)
round(Long.MaxValue - 1000L, -1)
round(BigDecimal("1234"), -2)