如何在Java中将数字四舍五入到n个小数位
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/153724/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to round a number to n decimal places in Java
提问by Alex Spurling
What I would like is a method to convert a double to a string which rounds using the half-up method - i.e. if the decimal to be rounded is 5, it always rounds up to the next number. This is the standard method of rounding most people expect in most situations.
我想要的是一种将双精度数转换为使用加半法四舍五入的字符串的方法 - 即如果要四舍五入的小数是 5,它总是四舍五入到下一个数字。这是大多数人在大多数情况下所期望的四舍五入的标准方法。
I also would like only significant digits to be displayed - i.e. there should not be any trailing zeroes.
我也希望只显示有效数字 - 即不应该有任何尾随零。
I know one method of doing this is to use the String.format
method:
我知道这样做的一种方法是使用以下String.format
方法:
String.format("%.5g%n", 0.912385);
returns:
返回:
0.91239
which is great, however it always displays numbers with 5 decimal places even if they are not significant:
这很好,但是它总是显示带有 5 个小数位的数字,即使它们不重要:
String.format("%.5g%n", 0.912300);
returns:
返回:
0.91230
Another method is to use the DecimalFormatter
:
另一种方法是使用DecimalFormatter
:
DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);
returns:
返回:
0.91238
However as you can see this uses half-even rounding. That is it will round down if the previous digit is even. What I'd like is this:
但是,正如您所看到的,这使用了半偶数舍入。也就是说,如果前一个数字是偶数,它将四舍五入。我想要的是这个:
0.912385 -> 0.91239
0.912300 -> 0.9123
What is the best way to achieve this in Java?
在 Java 中实现这一目标的最佳方法是什么?
采纳答案by curtisk
Use setRoundingMode
, set the RoundingMode
explicitly to handle your issue with the half-even round, then use the format pattern for your required output.
使用setRoundingMode
,RoundingMode
明确设置以处理半偶数回合的问题,然后使用所需输出的格式模式。
Example:
例子:
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));
}
gives the output:
给出输出:
12
123.1235
0.23
0.1
2341234.2125
EDIT: The original answer does not address the accuracy of the double values. That is fine if you don't care much whether it rounds up or down. But if you want accurate rounding, then you need to take the expected accuracy of the values into account. Floating point values have a binary representation internally. That means that a value like 2.7735 does not actually have that exact value internally. It can be slightly larger or slightly smaller. If the internal value is slightly smaller, then it will not round up to 2.7740. To remedy that situation, you need to be aware of the accuracy of the values that you are working with, and add or subtract that value before rounding. For example, when you know that your values are accurate up to 6 digits, then to round half-way values up, add that accuracy to the value:
编辑:原始答案没有解决双精度值的准确性。如果您不太关心它是向上还是向下取整,那很好。但是,如果您想要精确舍入,则需要考虑值的预期精度。浮点值在内部具有二进制表示。这意味着像 2.7735 这样的值实际上在内部没有那个确切的值。它可以稍大或稍小。如果内部值稍小,则不会向上取整到 2.7740。要纠正这种情况,您需要了解您正在使用的值的准确性,并在四舍五入之前添加或减去该值。例如,当您知道您的值精确到 6 位时,然后要将中间值向上舍入,将该精度添加到值中:
Double d = n.doubleValue() + 1e-6;
To round down, subtract the accuracy.
要向下取整,请减去准确度。
回答by asterite
Assuming value
is a double
, you can do:
假设value
是 a double
,你可以这样做:
(double)Math.round(value * 100000d) / 100000d
That's for 5 digits precision. The number of zeros indicate the number of decimals.
那是 5 位精度。零的个数表示小数位数。
回答by Chris Cudmore
double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;
回答by Milhous
You can also use the
您还可以使用
DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);
to make sure you have the trailing 0's.
以确保您有尾随的 0。
回答by MetroidFan2002
new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);
will get you a BigDecimal
. To get the string out of it, just call that BigDecimal
's toString
method, or the toPlainString
method for Java 5+ for a plain format string.
会给你一个BigDecimal
. 要从中取出字符串,只需调用 thatBigDecimal
的toString
方法,或者调用toPlainString
Java 5+的方法来获取纯格式字符串。
Sample program:
示例程序:
package trials;
import java.math.BigDecimal;
public class Trials {
public static void main(String[] args) {
int yourScale = 10;
System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
}
回答by Ovesh
回答by user593581
Suppose you have
假设你有
double d = 9232.129394d;
you can use BigDecimal
您可以使用 BigDecimal
BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();
or without BigDecimal
或没有 BigDecimal
d = Math.round(d*100)/100.0d;
with both solutions d == 9232.13
两种解决方案 d == 9232.13
回答by Amit
You could use the following utility method-
您可以使用以下实用方法-
public static double round(double valueToRound, int numberOfDecimalPlaces)
{
double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
double interestedInZeroDPs = valueToRound * multipicationFactor;
return Math.round(interestedInZeroDPs) / multipicationFactor;
}
回答by Ivan
@Milhous: the decimal format for rounding is excellent:
@Milhous:四舍五入的十进制格式非常好:
You can also use the
DecimalFormat df = new DecimalFormat("#.00000"); df.format(0.912385);
to make sure you have the trailing 0's.
您还可以使用
DecimalFormat df = new DecimalFormat("#.00000"); df.format(0.912385);
以确保您有尾随的 0。
I would add that this method is very good at providing an actual numeric, rounding mechanism - not only visually, but also when processing.
我要补充的是,这种方法非常擅长提供实际的数字舍入机制——不仅在视觉上,而且在处理时也是如此。
Hypothetical: you have to implement a rounding mechanism into a GUI program. To alter the accuracy / precision of a result output simply change the caret format (i.e. within the brackets). So that:
假设:您必须在 GUI 程序中实现舍入机制。要更改结果输出的准确度/精确度,只需更改插入符号格式(即在括号内)。以便:
DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);
would return as output: 0.912385
将作为输出返回: 0.912385
DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);
would return as output: 0.91239
将作为输出返回: 0.91239
DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);
would return as output: 0.9124
将作为输出返回: 0.9124
[EDIT: also if the caret format is like so ("#0.############") and you
enter a decimal, e.g. 3.1415926, for argument's sake, DecimalFormat
does not produce any garbage (e.g. trailing zeroes) and will return:
3.1415926
.. if you're that way inclined. Granted, it's a little verbose
for the liking of some dev's - but hey, it's got a low memory footprint
during processing and is very easy to implement.]
[编辑:此外,如果插入符号格式是这样的(“#0.############”)并且您输入一个小数,例如 3.1415926,为了参数,DecimalFormat 不会产生任何垃圾(例如尾随零)并将返回:
3.1415926
.. 如果你有这种倾向。诚然,这对于某些开发人员的喜好来说有点冗长 - 但是,嘿,它在处理过程中的内存占用很低,并且非常容易实现。]
So essentially, the beauty of DecimalFormat is that it simultaneously handles the string appearance - as well as the level of rounding precision set. Ergo: you get two benefits for the price of one code implementation. ;)
所以本质上,DecimalFormat 的美妙之处在于它同时处理字符串外观 - 以及舍入精度设置的级别。因此:您可以以一个代码实现的价格获得两个好处。;)
回答by Ivan
If you really want decimal numbers for calculation (and not only for output), do not use a binary-based floating point format like double.
如果您确实需要十进制数进行计算(而不仅仅是用于输出),请不要使用基于二进制的浮点格式,如 double。
Use BigDecimal or any other decimal-based format.
I do use BigDecimal for calculations, but bear in mind it is dependent on the size of numbers you're dealing with. In most of my implementations, I find parsing from double or integer to Long is sufficient enough for very large number calculations.
我确实使用 BigDecimal 进行计算,但请记住它取决于您正在处理的数字的大小。在我的大多数实现中,我发现从 double 或 integer 解析为 Long 足以进行非常大的数字计算。
In fact, I've recently used parsed-to-Long to get accurate representations (as opposed to hex results) in a GUI for numbers as big as ################################# characters (as an example).
事实上,我最近在 GUI 中使用 parsed-to-Long 来获得准确的表示(而不是十六进制结果),以获取################## 大的数字############### 字符(作为示例)。