DecimalFormat with RoundingMode.HALF_UP

僤鯓⒐⒋嵵緔 提交于 2019-12-20 04:25:28

问题


Having a simple code

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))
}

I got the following output:

-0,03 <-- ok

-0,01 <-- expecting -0,02

-0 <-- expecting -0,01

0 <-- expecting 0,01

0,01 <--- expecting 0,02

0,03 <-- ok

Do I correctly understand RoundingMode.HALF_UP meaning?

P.S. I had found, that using doubles instead of floats solve the problem. So println(f.format(0.005.toDouble())) works, giving expected 0.1.


回答1:


What the documentation says about RoundingMode.HALF_UP is:

Rounding mode to round towards "nearest neighbor" unless both neighbors are equidistant, in which case round up.

While that might look like the behavior you're looking for, these are decimal floats, and they have a hard time being represented in memory. There's a great read on it on the Oracle site.

So, it seems that -0.005 and -0.015 both are closer (nearest neighbor) to -0.01 than anything else, so they both are formatted as -0.01. To make your code do what you want it do to, is to change your rounding mode to:

roundingMode = RoundingMode.UP

The output of running that is:

-0.03
-0.02
-0.01
0.01
0.02
0.03

Which is exactly what you expected. If you do want your code to work, you can use the following approach though:

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")))
}



回答2:


Never ever use float or double if you want exact numbers to show up. If you round and want the rounding to happen on a solid base, you don't want float or double neither ;-)

Your sample using double would also give wrong results. Your sample using BigDecimal will give the results you expect. So... stick with BigDecimal if you want to be safe(r).

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")))
}


来源:https://stackoverflow.com/questions/53740617/decimalformat-with-roundingmode-half-up

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!