双精度数四舍五入到小数点后两位

发布于 2024-08-31 16:43:22 字数 111 浏览 3 评论 0 原文

如果值为 200.3456,则应将其格式设置为 200.34。 如果是200,那么它应该是200.00

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(13

雨的味道风的声音 2024-09-07 16:43:22

下面是一个实用程序,可以将双精度数舍入(而不是截断)到指定的小数位数。

例如:

round(200.3456, 2); // returns 200.35

原始版本;小心

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

这个在小数位数非常多(例如round(1000.0d, 17))或大整数部分(例如圆形(90080070060.1d, 9))。感谢 Sloin 指出了这一点。

多年来,我一直在使用上面的方法将“不太大”的双精度数四舍五入到小数点后 2 或 3 位(例如,出于记录目的以秒为单位清理时间:27.987654321987 -> 27.99)。但我想最好避免它,因为更可靠的方法很容易获得,而且代码也更简洁。

因此,请使用这个

(改编自Louis Wasserman的这个答案Sean Owen 的这个。)

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

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

请注意,HALF_UP 是“学校通常教授的”舍入模式。如果您怀疑,请仔细阅读 RoundingMode 文档需要其他东西,例如银行家舍入

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

在任何情况下,

始终记住使用 floatdouble< 的浮点表示/code> 不精确
例如,考虑以下表达式:

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

为了准确起见,您想要使用BigDecimal。在此过程中,请使用采用 String 的构造函数,而不是采用 double 的构造函数。例如,尝试执行以下内容:

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

关于该主题的一些出色的进一步阅读:


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

具体来说,请注意 round(200, 0) 返回 200.0。如果你想输出“200.00”,你应该先舍入然后格式化结果以进行输出(这在 Jesper 的答案)。

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.

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.

So, use this instead

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

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

    BigDecimal bd = BigDecimal.valueOf(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.

Of course, if you prefer, you can inline the above into a one-liner:
new BigDecimal(value).setScale(places, 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:

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:


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

ヅ她的身影、若隐若现 2024-09-07 16:43:22

如果您只想打印小数点后两位数字的 double,请使用如下内容:

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

如果您希望将结果保存在 String 中,而不是打印到在控制台,使用具有相同参数的 String.format()

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

或者使用类 DecimalFormat

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

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 result = String.format("%.2f", value);

Or use class DecimalFormat:

DecimalFormat df = new DecimalFormat("####0.00");
System.out.println("Value: " + df.format(value));
萌化 2024-09-07 16:43:22

我认为这更容易:

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

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

请注意,这实际上会为您进行舍入,而不仅仅是格式化。

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.

暮凉 2024-09-07 16:43:22

最简单的方法就是做这样的把戏;

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

如果 val 从 200.3456 开始,那么它会变为 20034.56,然后四舍五入到 20035,然后我们将其除以得到 200.34。

如果你想总是向下舍入,我们总是可以通过转换为 int 来截断:

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

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

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.

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.

如果没有 2024-09-07 16:43:22

请使用 Apache 公共数学

Precision.round(10.4567, 2)

Please use Apache commons math:

Precision.round(10.4567, 2)
我很OK 2024-09-07 16:43:22
function Double round2(Double val) {
    return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}

注意 toString()!!!!

这是因为 BigDecimal 转换了 double 的精确二进制形式!

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

// 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;
function Double round2(Double val) {
    return new BigDecimal(val.toString()).setScale(2,RoundingMode.HALF_UP).doubleValue();
}

Note the toString()!!!!

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

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;
握住我的手 2024-09-07 16:43:22
double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");      
System.out.println(df.format(value));
double value= 200.3456;
DecimalFormat df = new DecimalFormat("0.00");      
System.out.println(df.format(value));
伪装你 2024-09-07 16:43:22

例如,如果您确实想要相同的双精度值,但以您想要的方式四舍五入,则可以使用 BigDecimal

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

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

new BigDecimal(myValue).setScale(2, RoundingMode.HALF_UP).doubleValue();
猫卆 2024-09-07 16:43:22
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
double d = 28786.079999999998;
String str = String.format("%1.2f", d);
d = Double.valueOf(str);
不寐倦长更 2024-09-07 16:43:22

对双精度数进行四舍五入通常不是人们想要的。相反,使用 String.format() 以所需的格式表示它。

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

謸气贵蔟 2024-09-07 16:43:22

对于两位四舍五入数字。非常简单,您基本上是在更新变量,而不仅仅是 DecimalFormat 所做的显示目的。

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

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

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

风吹过旳痕迹 2024-09-07 16:43:22

在你的问题中,你似乎也想避免对数字进行四舍五入?我认为 .format() 会使用半向上舍入数字,afaik?
因此,如果你想四舍五入,200.3456 应该是 200.35,精度为 2。但在你的情况下,如果你只想要前 2 个,然后丢弃其余的?

您可以将其乘以 100,然后转换为 int(或取数字的下限),然后再次除以 100。

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

不过,对于接近边界的非常非常大的数字,您可能会遇到问题。在这种情况下,转换为字符串并进行子字符串化也同样容易。

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 to round, 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?

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

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.

总攻大人 2024-09-07 16:43:22
value = (int)(value * 100 + 0.5) / 100.0;
value = (int)(value * 100 + 0.5) / 100.0;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文