具有RoundingMode.HALF_UP的DecimalFormat

时间:2018-12-12 10:09:35

标签: math kotlin rounding number-formatting

具有简单的代码

import java.math.RoundingMode
import java.text.DecimalFormat

fun main(args: Array<String>) {
  val f = DecimalFormat("#.##").apply { roundingMode = RoundingMode.HALF_UP }
  println(f.format(-0.025f))
  println(f.format(-0.015f))
  println(f.format(-0.005f))
  println(f.format(0.005f))
  println(f.format(0.015f))
  println(f.format(0.025f))
}

我得到以下输出:

  

-0,03 <-好的

     

-0,01 <-预期-0,02

     

-0 <-期望-0,01

     

0 <-期望为0.01

     

0,01 <---期望0,02

     

0,03 <-好的

我是否正确理解RoundingMode.HALF_UP的含义?

PS 我发现,使用双精度代替浮点数可以解决问题。因此println(f.format(0.005.toDouble()))可以正常工作,并提供预期的0.1

2 个答案:

答案 0 :(得分:1)

文档中关于RoundingMode.HALF_UP的内容是:

  

除非两个邻居都等距,否则舍入模式将朝“最近的邻居”舍入。

虽然看起来像您想要的行为,但是它们是十进制浮点数,它们很难在内存中表示。在the Oracle site上有很多读物。

因此,似乎-0.005和-0.015都比其他任何东西都更接近(最近的邻居)-0.01,因此它们的格式都为-0.01。要使您的代码执行您想要的操作,就是将舍入模式更改为:

roundingMode = RoundingMode.UP

运行的输出为:

-0.03
-0.02
-0.01
0.01
0.02
0.03

这正是您所期望的。如果您确实希望代码正常工作,则可以使用以下方法:

import java.math.BigDecimal
import java.math.RoundingMode
import java.text.DecimalFormat

fun main(args: Array<String>) {
    val f = DecimalFormat("#.##").apply { roundingMode = RoundingMode.HALF_UP }
    println(f.format( BigDecimal("-1000.045")))
    println(f.format( BigDecimal("-1000.035")))
    println(f.format( BigDecimal("-1000.025")))
    println(f.format( BigDecimal("-1000.015")))
    println(f.format( BigDecimal("-1000.005")))
}

答案 1 :(得分:0)

如果要显示准确的数字,切勿使用floatdouble。如果您舍入并希望舍入在坚实的基础上进行,则您都不希望floatdouble都不;;)

您使用double的示例也会给出错误的结果。使用BigDecimal的示例将提供您期望的结果。因此,如果您想安全起见,请坚持使用BigDecimal

fun main(args: Array<String>) {
  val f = DecimalFormat("#.##").apply { roundingMode = RoundingMode.HALF_UP }
  println(f.format(BigDecimal("-0.025")))
  println(f.format(BigDecimal("-0.015")))
  println(f.format(BigDecimal("-0.005")))
  println(f.format(BigDecimal("0.005")))
  println(f.format(BigDecimal("0.015")))
  println(f.format(BigDecimal("0.025")))
}