java怎么给数字加小数点_如何在Java中将数字四舍五入到小数点后n位

我想要的是一种将双精度数转换为使用Half-up方法取整的字符串的方法-即,如果要取整的小数为5,则始终将其取整为下一个数字。 这是大多数人在大多数情况下期望的四舍五入标准方法。

我也希望只显示有效数字-即不应有任何尾随零。

我知道这样做的一种方法是使用String.format方法:

String.format("%.5g%n", 0.912385);

返回:

0.91239

这很好,但是即使数字不重要,它也始终显示5位小数:

String.format("%.5g%n", 0.912300);

返回:

0.91230

另一种方法是使用DecimalFormatter :

DecimalFormat df = new DecimalFormat("#.#####");

df.format(0.912385);

返回:

0.91238

但是,如您所见,这使用了半数舍入。 如果前一位是偶数,它将四舍五入。 我想要的是这样的:

0.912385 -> 0.91239

0.912300 -> 0.9123

用Java实现此目标的最佳方法是什么?

#1楼

正如其他一些人指出的那样,正确的答案是使用DecimalFormat或BigDecimal 。 浮点没有小数所以你不可能圆/截形到他们摆在首位的具体数量。 您必须使用十进制基数,这就是这两个类的作用。

我将以下代码作为该线程中所有答案的反示例,甚至在整个StackOverflow(以及其他地方)上发布,以作为建议,建议相乘然后截断再除法。 该技术的倡导者有责任解释为什么以下代码在超过92%的情况下会产生错误的输出。

public class RoundingCounterExample

{

static float roundOff(float x, int position)

{

float a = x;

double temp = Math.pow(10.0, position);

a *= temp;

a = Math.round(a);

return (a / (float)temp);

}

public static void main(String[] args)

{

float a = roundOff(0.0009434f,3);

System.out.println("a="+a+" (a % .001)="+(a % 0.001));

int count = 0, errors = 0;

for (double x = 0.0; x < 1; x += 0.0001)

{

count++;

double d = x;

int scale = 2;

double factor = Math.pow(10, scale);

d = Math.round(d * factor) / factor;

if ((d % 0.01) != 0.0)

{

System.out.println(d + " " + (d % 0.01));

errors++;

}

}

System.out.println(count + " trials " + errors + " errors");

}

}

该程序的输出:

10001 trials 9251 errors

编辑:为了解决下面的一些评论,我使用BigDecimal和new MathContext(16)测试循环的模数部分,如下所示:

public static void main(String[] args)

{

int count = 0, errors = 0;

int scale = 2;

double factor = Math.pow(10, scale);

MathContext mc = new MathContext(16, RoundingMode.DOWN);

for (double x = 0.0; x < 1; x += 0.0001)

{

count++;

double d = x;

d = Math.round(d * factor) / factor;

BigDecimal bd = new BigDecimal(d, mc);

bd = bd.remainder(new BigDecimal("0.01"), mc);

if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)

{

System.out.println(d + " " + bd);

errors++;

}

}

System.out.println(count + " trials " + errors + " errors");

}

结果:

10001 trials 4401 errors

#2楼

Real的Java How-to 发布了此解决方案,该解决方案也与Java 1.6之前的版本兼容。

BigDecimal bd = new BigDecimal(Double.toString(d));

bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);

return bd.doubleValue();

#3楼

假设value是double ,则可以执行以下操作:

(double)Math.round(value * 100000d) / 100000d

这是5位数字的精度。 零数表示小数位数。

#4楼

double myNum = .912385;

int precision = 10000; //keep 4 digits

myNum= Math.floor(myNum * precision +.5)/precision;

#5楼

使用setRoundingMode ,显式设置RoundingMode以处理半个半个回合的问题,然后将格式模式用于所需的输出。

例:

DecimalFormat df = new DecimalFormat("#.####");

df.setRoundingMode(RoundingMode.CEILING);

for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {

Double d = n.doubleValue();

System.out.println(df.format(d));

}

给出输出:

12

123.1235

0.23

0.1

2341234.2125

编辑 :原始答案未解决双精度值的准确性。 如果您不在乎它是向上还是向下,那很好。 但是,如果要精确舍入,则需要考虑值的预期准确性。 浮点值在内部具有二进制表示形式。 这意味着像2.77395这样的值实际上在内部没有该确切值。 它可以稍大或略小。 如果内部值稍小,则不会舍入到2.7740。 为了解决这种情况,您需要了解所使用的值的准确性,并在舍入之前添加或减去该值。 例如,当您知道自己的值在6位数字之内是正确的,然后将其四舍五入时,请将精度添加到值中:

Double d = n.doubleValue() + 1e-6;

要舍入,请减去精度。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值