我想要的是一种将double转换为使用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中实现这一目标的最佳方法是什么?
29 回答
我来到这里只是想要一个如何围绕数字的简单答案 . 这是提供这一点的补充答案 .
如何在Java中舍入数字
最常见的情况是使用
Math.round()
.数字四舍五入到最接近的整数 .
.5
值向上舍入 . 如果您需要不同的舍入行为,则可以使用其他Math函数之一 . 请参阅下面的比较 .轮
如上所述,这舍入到最接近的整数 .
.5
小数向上舍入 . 此方法返回int
.ceil
任何十进制值都会向上舍入到下一个整数 . 它转到 ceil ing . 此方法返回
double
.楼
任何十进制值都向下舍入到下一个整数 . 此方法返回
double
.rint
这类似于round,十进制值四舍五入到最接近的整数 . 但是,与
round
不同,.5
值舍入为偶数 . 此方法返回double
.假设
value
是double
,您可以这样做:这是5位精度 . 零的数量表示小数位数 .
我同意所选答案使用
DecimalFormat
---或者BigDecimal
.请先阅读下面的 Update !
但是,如果您想要对double值进行舍入并获得double值结果,则可以使用上面提到的org.apache.commons.math3.util.Precision.round(..) . 实现使用BigDecimal,速度慢并且会产生垃圾 .
decimal4j库中的DoubleRounder实用程序提供了类似但快速且无垃圾的方法:
会输出
见https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility
免责声明:我参与了decimal4j项目 .
Update: 正如@iaforek所指出的,DoubleRounder有时会返回违反直觉的结果 . 原因是它在数学上执行正确的舍入 . 例如
DoubleRounder.round(256.025d, 2)
将向下舍入到256.02,因为表示为256.025d的double值略小于有理值256.025,因此将向下舍入 .Notes:
此行为与
BigDecimal(double)
构造函数的行为非常相似(但不使用valueOf(double)
,它使用字符串构造函数) .首先可以通过双舍入步骤来避免问题,但是它很复杂,我不会在这里详细说明
由于这些原因以及本文中上面提到的一切,我都是 cannot recommend to use DoubleRounder .
您可以使用DecimalFormat类 .
由于我没有找到关于这个主题的完整答案,我已经整理了一个应该正确处理这个问题的课程,并支持:
Formatting :使用一定数量的小数位轻松地将double格式化为字符串
Parsing :将格式化的值解析为double
Locale :使用默认语言环境格式化和解析
Exponential notation :在某个阈值后开始使用指数表示法
Usage is pretty simple :
(为了这个例子,我使用的是自定义语言环境)
Here is the class :
你也可以使用
确保你有0的结尾 .
正如其他人所说,正确的答案是使用
DecimalFormat
或BigDecimal
. 浮点没有小数位,因此您不可能首先将其舍入/截断为特定数量的小数位 . 你必须使用十进制基数,这就是这两个类的作用 .我发布了以下代码作为这个线程中所有答案的反例 - 实际上遍布StackOverflow(以及其他地方)建议乘法,然后是截断,然后是除法 . 这种技术的拥护者有责任解释为什么以下代码在超过92%的情况下产生错误的输出 .
该计划的输出:
EDIT: 为了解决下面的一些注释,我使用
BigDecimal
和new MathContext(16)
为模数运算重新设置了测试循环的模数部分,如下所示:结果:
您可以使用以下实用方法 -
下面的代码段显示了如何显示n位数 . 诀窍是将变量pp设置为1,然后是n个零 . 在下面的示例中,变量pp值有5个零,因此将显示5个数字 .
请记住,String.format()和DecimalFormat使用默认的Locale生成字符串 . 因此,他们可以使用点或逗号作为整数和小数部分之间的分隔符来编写带格式的数字 . 要确保圆角字符串采用您想要的格式,请使用java.text.NumberFormat:
将以英语语言环境打印(无论您的语言环境是什么):0.99 123.57 123.00
这个例子来自Farenda - how to convert double to String correctly .
如果你真的想要十进制数来计算(而不仅仅是输出),不要使用像double这样的基于二进制的浮点格式 .
我确实使用BigDecimal进行计算,但请记住它取决于您正在处理的数字的大小 . 在我的大多数实现中,我发现从double或integer到Long的解析足以进行大量计算 .
事实上,我最近使用parsed-to-Long在GUI中获得与##################一样大的数字的准确表示(而不是十六进制结果) ###############字符(作为示例) .
您可以使用BigDecimal
参考:http://www.javabeat.net/precise-rounding-of-decimals-using-rounding-mode-enumeration/
如果您使用的是具有最小JDK的技术 . 这是一种没有任何Java库的方法:
通常,舍入是通过缩放来完成的:
round(num / p) * p
以防有人仍然需要帮助 . 这个解决方案非常适合我 .
返回带有所需输出的
String
.Real的Java How-to posts这个解决方案,它也兼容Java 1.6之前的版本 .
简洁的解决方案:
另见,https://stackoverflow.com/a/22186845/212950感谢jpdymond提供此功能 .
@Milhous:舍入的十进制格式非常好:
我想补充一点,这种方法非常擅长提供一种实际的数字舍入机制 - 不仅在视觉上,而且在处理时 .
假设:您必须在GUI程序中实现舍入机制 . 要改变结果输出的准确度/精度,只需更改插入符号格式(即括号内) . 以便:
将作为输出返回:
0.912385
将作为输出返回:
0.91239
将作为输出返回:
0.9124
[编辑:如果插入符号格式如此("#0.############")并输入小数,例如3.1415926,为了论证的缘故,DecimalFormat不会产生任何垃圾(例如尾随零)并将返回:
3.1415926
..如果你对某些开发人员的喜好有点冗长's - but hey, it' s在处理期间内存占用空间很小并且非常容易实行 . ]从本质上讲,DecimalFormat的优点在于它同时处理字符串外观 - 以及舍入精度集的级别 . Ergo:您可以从一个代码实现的价格中获得两个好处 . ;)
使用setRoundingMode,明确设置RoundingMode来处理半偶数问题,然后使用格式模式输出所需的输出 .
例:
给出输出:
如果您使用
DecimalFormat
将double
转换为String
,则非常简单:有几个
RoundingMode
枚举值可供选择,具体取决于您需要的行为 .会给你一个
BigDecimal
. 要从中获取字符串,只需调用BigDecimal
的toString
方法或Java 5的toPlainString
方法作为普通格式字符串 .示例程序:
如果你考虑5或n个小数 . 可能是这个答案解决你的问题 .
Output will be: 123.0 1
这可以通过循环和递归函数来解决 .
DecimalFormat是输出的最佳方式,但我不喜欢它 . 我总是这样做,因为它返回double值 . 所以我可以使用它而不仅仅是输出 .
要么
如果需要大小数位值,则可以使用BigDecimal . 无论如何
.0
很重要 . 没有它,0.33333d5的舍入返回0.33333,只允许9位数 . 没有.0
的第二个函数有0.30000返回0.30000000000000004的问题 .以下是您希望结果为String时可以使用的内容摘要:
如果您希望
double
作为结果,这里建议您可以使用哪些库 . 我不建议将其用于字符串转换,因为double可能无法准确表示您想要的内容(请参阅例如here):来自Apache Commons Math的
来自柯尔特的
来自Weka的
假设你有
你可以用BigDecimal
要么没有BigDecimal
两种解决方案
d == 9232.13
其中dp =你想要的小数位,而值是double .
为此,我们可以使用此格式化程序:
要么:
使用此方法始终获得两位小数:
定义此值:
使用该方法我们可以得到以下结果:
demo online.
试试这个:org.apache.commons.math3.util.Precision.round(double x,int scale)
见:http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/Precision.html
Apache Commons数学图书馆主页是:http://commons.apache.org/proper/commons-math/index.html
该方法的内部实现是: