小数点后两位[重复]

时间:2022-06-21 16:34:05

This question already has an answer here:

这个问题已经有了答案:

If the value is 200.3456, it should be formatted to 200.34. If it is 200, then it should be 200.00.

如果值是200.3456,则应该将其格式化为200.34。如果是200,那么应该是200。00。

13 个解决方案

#1


636  

Here's an utility that rounds (instead of truncating) a double to specified number of decimal places.

这里有一个实用程序,它可以四舍五入(而不是截断)到指定的小数位数。

For example:

例如:

round(200.3456, 2); // returns 200.35

Original version; watch out with this

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    long factor = (long) Math.pow(10, places);
    value = value * factor;
    long tmp = Math.round(value);
    return (double) tmp / factor;
}

This breaks down badly in corner cases with either a very high number of decimal places (e.g. round(1000.0d, 17)) or large integer part (e.g. round(90080070060.1d, 9)). Thanks to Sloin for pointing this out.

这在小数位数非常高(例如:round(1000.0d, 17))或大整数部分(例如round(90080070060.1d, 9)的情况下会很糟糕。多亏了Sloin指出了这一点。

I've been using the above to round "not-too-big" doubles to 2 or 3 decimal places happily for years (for example to clean up time in seconds for logging purposes: 27.987654321987 -> 27.99). But I guess it's best to avoid it, since more reliable ways are readily available, with cleaner code too.

我一直在使用上面的“不太大”的两倍到2或3个小数,这是多年来的快乐(例如,为了记录日志的目的,在几秒钟内清理时间:27.987654321987 -> 27.99)。但我想最好还是避免它,因为更可靠的方法很容易获得,而且代码也更干净。

So, use this instead

(Adapted from this answer by Louis Wasserman and this one by Sean Owen.)

(改编自路易斯·瓦瑟曼(Louis Wasserman)和肖恩·欧文(Sean Owen)的回答。)

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    BigDecimal bd = new BigDecimal(value);
    bd = bd.setScale(places, RoundingMode.HALF_UP);
    return bd.doubleValue();
}

Note that HALF_UP is the rounding mode "commonly taught at school". Peruse the RoundingMode documentation, if you suspect you need something else such as Bankers’ Rounding.

注意,HALF_UP是学校常见的舍入模式。仔细阅读RoundingMode文档,如果您怀疑需要其他东西,比如银行家的四舍五入。

Of course, if you prefer, you can inline the above into a one-liner:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()

当然,如果您愿意,可以将上面的内容内联到一行中:new BigDecimal(value)。setScale(地方,RoundingMode.HALF_UP).doubleValue()

And in every case

Always remember that floating point representations using float and double are inexact. For example, consider these expressions:

记住,使用浮点和双精度浮点表示是不精确的。例如,考虑以下表达式:

999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001

For exactness, you want to use BigDecimal. And while at it, use the constructor that takes a String, never the one taking double. For instance, try executing this:

为了精确,您需要使用BigDecimal。同时,使用构造函数来获取字符串,而不是双精度。例如,尝试执行以下操作:

System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));

Some excellent further reading on the topic:

关于这个话题的一些优秀的进一步阅读:

  • Item 48: "Avoid float and double if exact answers are required" in Effective Java (2nd ed) by Joshua Bloch
  • 第48项:“避免浮动和双重,如果需要确切的答案”在有效的Java(第二版)由Joshua Bloch
  • What Every Programmer Should Know About Floating-Point Arithmetic
  • 每个程序员都应该知道浮点运算!

If you wanted String formatting instead of (or in addition to) strictly rounding numbers, see the other answers.

如果您想要字符串格式,而不是(或除了)严格的四舍五入数字,请参阅其他答案。

Specifically, note that round(200, 0) returns 200.0. If you want to output "200.00", you should first round and then format the result for output (which is perfectly explained in Jesper's answer).

具体地说,请注意,第一轮(200,0)返回200.0。如果您想要输出“200.00”,您应该在第一轮中,然后格式化输出结果(这在Jesper的答案中得到了很好的解释)。

#2


258  

If you just want to print a double with two digits after the decimal point, use something like this:

如果你只想在小数点后打印一个两位数的双位数,可以使用如下方法:

double value = 200.3456;
System.out.printf("Value: %.2f", value);

If you want to have the result in a String instead of being printed to the console, use String.format() with the same arguments:

如果您希望结果是字符串,而不是打印到控制台,请使用String.format(),并使用相同的参数:

String result = String.format("%.2f", value);

Or use class DecimalFormat:

或者使用DecimalFormat类:

DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));

#3


104  

I think this is easier:

我认为这更容易:

double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");      
time = Double.valueOf(df.format(time));

System.out.println(time); // 200.35

Note that this will actually do the rounding for you, not just formatting.

注意,这将为您实现舍入,而不仅仅是格式化。

#4


53  

The easiest way, would be to do a trick like this;

最简单的方法,就是做这样的魔术;

double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;

if val starts at 200.3456 then it goes to 20034.56 then it gets rounded to 20035 then we divide it to get 200.34.

如果val从200.3456开始,到20034。56,然后四舍五入到20035,然后除以得到20034。34。

if you wanted to always round down we could always truncate by casting to an int:

如果你想一直往下,我们可以把它截成一个整数:

double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;

This technique will work for most cases because for very large doubles (positive or negative) it may overflow. but if you know that your values will be in an appropriate range then this should work for you.

这种技术在大多数情况下都是有效的,因为对于非常大的双精度数(正的或负的),它可能会溢出。但是如果你知道你的价值会在一个合适的范围内,那么这个应该对你有用。

#5


40  

Please use Apache commons math:

请使用Apache commons math:

Precision.round(10.4567, 2)

#6


25  

function Double round2(Double val) {
    return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}

Note the toString()!!!!

注意toString()! ! ! !

This is because BigDecimal converts the exact binary form of the double!!!

这是因为BigDecimal可以转换双精度浮点数的二进制形式!!!

These are the various suggested methods and their fail cases.

这些是各种建议的方法和失败的案例。

// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue() 

Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()

Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAIN - Math.round(val * 100.d) / 100.0d  

Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - new DecimalFormat("0.00").format(val) 
// By default use half even, works if you change mode to half_up 

Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;

#7


14  

If you really want the same double, but rounded in the way you want you can use BigDecimal, for example

如果你真的想要相同的双精度浮点数,但是用你想要的方式四舍五入,你可以使用BigDecimal

new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();

#8


14  

double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");      
System.out.println(df.format(value));

#9


13  

double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);

#10


8  

Rounding a double is usually not what one wants. Instead, use String.format() to represent it in the desired format.

四舍五入一倍通常不是一个人想要的。相反,使用String.format()以期望的格式表示它。

#11


4  

For two rounding digits. Very simple and you are basically updating the variable instead of just display purposes which DecimalFormat does.

两排数字。非常简单,你基本上是在更新变量,而不是仅仅显示DecimalFormat的目的。

x = Math.floor(x * 100) / 100;

x =数学。楼层(x * 100) / 100;

#12


0  

in your question it seems that you want to avoid rounding the numbers as well? i think .format() will round the numbers using half-up, afaik?
so if you want rounding, 200.3456 should be 200.35 for a precision of 2. but in your case, if you just want the first 2 and then discard the rest... ??:

在你的问题中,似乎你也想避免把数字四舍五入?我想.format()会用半价整数吗?如果你想四舍五入,200.3456应该是200.35,精度为2。但在你的情况下,如果你只想要前两个,然后丢弃剩下的……? ?:

you could multiply it by 100 and then cast to an int (or taking the floor of the number), before dividing by 100 again.

你可以把它乘以100,然后转换成整数(或者取数字的底),然后再除以100。

200.3456 * 100 = 20034.56;
(int) 20034.56 = 20034;
20034/100.0 = 200.34;

200.3456 * 100 = 20034.56;(int)20034.56 = 20034;20034/100.0 = 200.34;

you might have issues with really really big numbers close to the boundary though. in which case converting to a string and substring'ing it would work just as easily.

你可能会对接近边界的大数字产生问题。在这种情况下,将其转换为字符串并进行子字符串处理也同样容易。

#13


0  

value = (int)(value * 100 + 0.5) / 100.0;

#1


636  

Here's an utility that rounds (instead of truncating) a double to specified number of decimal places.

这里有一个实用程序,它可以四舍五入(而不是截断)到指定的小数位数。

For example:

例如:

round(200.3456, 2); // returns 200.35

Original version; watch out with this

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    long factor = (long) Math.pow(10, places);
    value = value * factor;
    long tmp = Math.round(value);
    return (double) tmp / factor;
}

This breaks down badly in corner cases with either a very high number of decimal places (e.g. round(1000.0d, 17)) or large integer part (e.g. round(90080070060.1d, 9)). Thanks to Sloin for pointing this out.

这在小数位数非常高(例如:round(1000.0d, 17))或大整数部分(例如round(90080070060.1d, 9)的情况下会很糟糕。多亏了Sloin指出了这一点。

I've been using the above to round "not-too-big" doubles to 2 or 3 decimal places happily for years (for example to clean up time in seconds for logging purposes: 27.987654321987 -> 27.99). But I guess it's best to avoid it, since more reliable ways are readily available, with cleaner code too.

我一直在使用上面的“不太大”的两倍到2或3个小数,这是多年来的快乐(例如,为了记录日志的目的,在几秒钟内清理时间:27.987654321987 -> 27.99)。但我想最好还是避免它,因为更可靠的方法很容易获得,而且代码也更干净。

So, use this instead

(Adapted from this answer by Louis Wasserman and this one by Sean Owen.)

(改编自路易斯·瓦瑟曼(Louis Wasserman)和肖恩·欧文(Sean Owen)的回答。)

public static double round(double value, int places) {
    if (places < 0) throw new IllegalArgumentException();

    BigDecimal bd = new BigDecimal(value);
    bd = bd.setScale(places, RoundingMode.HALF_UP);
    return bd.doubleValue();
}

Note that HALF_UP is the rounding mode "commonly taught at school". Peruse the RoundingMode documentation, if you suspect you need something else such as Bankers’ Rounding.

注意,HALF_UP是学校常见的舍入模式。仔细阅读RoundingMode文档,如果您怀疑需要其他东西,比如银行家的四舍五入。

Of course, if you prefer, you can inline the above into a one-liner:
new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue()

当然,如果您愿意,可以将上面的内容内联到一行中:new BigDecimal(value)。setScale(地方,RoundingMode.HALF_UP).doubleValue()

And in every case

Always remember that floating point representations using float and double are inexact. For example, consider these expressions:

记住,使用浮点和双精度浮点表示是不精确的。例如,考虑以下表达式:

999199.1231231235 == 999199.1231231236 // true
1.03 - 0.41 // 0.6200000000000001

For exactness, you want to use BigDecimal. And while at it, use the constructor that takes a String, never the one taking double. For instance, try executing this:

为了精确,您需要使用BigDecimal。同时,使用构造函数来获取字符串,而不是双精度。例如,尝试执行以下操作:

System.out.println(new BigDecimal(1.03).subtract(new BigDecimal(0.41)));
System.out.println(new BigDecimal("1.03").subtract(new BigDecimal("0.41")));

Some excellent further reading on the topic:

关于这个话题的一些优秀的进一步阅读:

  • Item 48: "Avoid float and double if exact answers are required" in Effective Java (2nd ed) by Joshua Bloch
  • 第48项:“避免浮动和双重,如果需要确切的答案”在有效的Java(第二版)由Joshua Bloch
  • What Every Programmer Should Know About Floating-Point Arithmetic
  • 每个程序员都应该知道浮点运算!

If you wanted String formatting instead of (or in addition to) strictly rounding numbers, see the other answers.

如果您想要字符串格式,而不是(或除了)严格的四舍五入数字,请参阅其他答案。

Specifically, note that round(200, 0) returns 200.0. If you want to output "200.00", you should first round and then format the result for output (which is perfectly explained in Jesper's answer).

具体地说,请注意,第一轮(200,0)返回200.0。如果您想要输出“200.00”,您应该在第一轮中,然后格式化输出结果(这在Jesper的答案中得到了很好的解释)。

#2


258  

If you just want to print a double with two digits after the decimal point, use something like this:

如果你只想在小数点后打印一个两位数的双位数,可以使用如下方法:

double value = 200.3456;
System.out.printf("Value: %.2f", value);

If you want to have the result in a String instead of being printed to the console, use String.format() with the same arguments:

如果您希望结果是字符串,而不是打印到控制台,请使用String.format(),并使用相同的参数:

String result = String.format("%.2f", value);

Or use class DecimalFormat:

或者使用DecimalFormat类:

DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));

#3


104  

I think this is easier:

我认为这更容易:

double time = 200.3456;
DecimalFormat df = new DecimalFormat("#.##");      
time = Double.valueOf(df.format(time));

System.out.println(time); // 200.35

Note that this will actually do the rounding for you, not just formatting.

注意,这将为您实现舍入,而不仅仅是格式化。

#4


53  

The easiest way, would be to do a trick like this;

最简单的方法,就是做这样的魔术;

double val = ....;
val = val*100;
val = Math.round(val);
val = val /100;

if val starts at 200.3456 then it goes to 20034.56 then it gets rounded to 20035 then we divide it to get 200.34.

如果val从200.3456开始,到20034。56,然后四舍五入到20035,然后除以得到20034。34。

if you wanted to always round down we could always truncate by casting to an int:

如果你想一直往下,我们可以把它截成一个整数:

double val = ....;
val = val*100;
val = (double)((int) val);
val = val /100;

This technique will work for most cases because for very large doubles (positive or negative) it may overflow. but if you know that your values will be in an appropriate range then this should work for you.

这种技术在大多数情况下都是有效的,因为对于非常大的双精度数(正的或负的),它可能会溢出。但是如果你知道你的价值会在一个合适的范围内,那么这个应该对你有用。

#5


40  

Please use Apache commons math:

请使用Apache commons math:

Precision.round(10.4567, 2)

#6


25  

function Double round2(Double val) {
    return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}

Note the toString()!!!!

注意toString()! ! ! !

This is because BigDecimal converts the exact binary form of the double!!!

这是因为BigDecimal可以转换双精度浮点数的二进制形式!!!

These are the various suggested methods and their fail cases.

这些是各种建议的方法和失败的案例。

// Always Good!
new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue() 

Double val = 260.775d; //EXPECTED 260.78
260.77 - WRONG - new BigDecimal(val).setScale(2,RoundingMode.HALF_UP).doubleValue()

Double val = 260.775d; //EXPECTED 260.78
260.77 - TRY AGAIN - Math.round(val * 100.d) / 100.0d  

Double val = 256.025d; //EXPECTED 256.03d
256.02 - OOPS - new DecimalFormat("0.00").format(val) 
// By default use half even, works if you change mode to half_up 

Double val = 256.025d; //EXPECTED 256.03d
256.02 - FAIL - (int)(val * 100 + 0.5) / 100.0;

#7


14  

If you really want the same double, but rounded in the way you want you can use BigDecimal, for example

如果你真的想要相同的双精度浮点数,但是用你想要的方式四舍五入,你可以使用BigDecimal

new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();

#8


14  

double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");      
System.out.println(df.format(value));

#9


13  

double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);

#10


8  

Rounding a double is usually not what one wants. Instead, use String.format() to represent it in the desired format.

四舍五入一倍通常不是一个人想要的。相反,使用String.format()以期望的格式表示它。

#11


4  

For two rounding digits. Very simple and you are basically updating the variable instead of just display purposes which DecimalFormat does.

两排数字。非常简单,你基本上是在更新变量,而不是仅仅显示DecimalFormat的目的。

x = Math.floor(x * 100) / 100;

x =数学。楼层(x * 100) / 100;

#12


0  

in your question it seems that you want to avoid rounding the numbers as well? i think .format() will round the numbers using half-up, afaik?
so if you want rounding, 200.3456 should be 200.35 for a precision of 2. but in your case, if you just want the first 2 and then discard the rest... ??:

在你的问题中,似乎你也想避免把数字四舍五入?我想.format()会用半价整数吗?如果你想四舍五入,200.3456应该是200.35,精度为2。但在你的情况下,如果你只想要前两个,然后丢弃剩下的……? ?:

you could multiply it by 100 and then cast to an int (or taking the floor of the number), before dividing by 100 again.

你可以把它乘以100,然后转换成整数(或者取数字的底),然后再除以100。

200.3456 * 100 = 20034.56;
(int) 20034.56 = 20034;
20034/100.0 = 200.34;

200.3456 * 100 = 20034.56;(int)20034.56 = 20034;20034/100.0 = 200.34;

you might have issues with really really big numbers close to the boundary though. in which case converting to a string and substring'ing it would work just as easily.

你可能会对接近边界的大数字产生问题。在这种情况下,将其转换为字符串并进行子字符串处理也同样容易。

#13


0  

value = (int)(value * 100 + 0.5) / 100.0;