// The number of 0s determines how many digits you want after the floating point
// (here one digit)
total = (double)Math.round(total * 10) / 10;
System.out.println(total); // prints 11.4
import java.math.BigDecimal;
/**
* Created by a wonderful programmer known as:
* Vincent Stoessel
* xaymaca@gmail.com
* on Mar 17, 2010 at 11:05:16 PM
*/
public class BigUp {
public static void main(String[] args) {
BigDecimal first, second, result ;
first = new BigDecimal("33.33333333333333") ;
second = new BigDecimal("100") ;
result = first.divide(second);
System.out.println("result is " + result);
//will print : result is 0.3333333333333333
}
}
为了插入我最喜欢的新语言groovy,这里有一个更简洁的例子:
import java.math.BigDecimal
def first = new BigDecimal("33.33333333333333")
def second = new BigDecimal("100")
println "result is " + first/second // will print: result is 0.33333333333333
public class doublePrecision {
public static void main(String[] args) {
BigDecimal total = new BigDecimal("0");
total = total.add(new BigDecimal("5.6"));
total = total.add(new BigDecimal("5.8"));
System.out.println(total);
}
}
22条答案
按热度按时间bprjcwpo1#
把所有的东西都乘以100,然后储存在一个很长的分币里。
5f0d552i2#
很确定你可以把它变成一个三行的例子。:)
如果您想要精确的精度,请使用bigdecimal。否则,可以使用int乘以10^的任意精度。
mqxuamgl3#
为什么不使用math类中的round()方法呢?
2lpgd9684#
不要用大小数浪费你的精力。99.99999%的情况下你不需要它。java double类型是cource a
1tuwyuhd5#
如果除了使用双值之外别无选择,可以使用下面的代码。
djp7away6#
你不能,因为7.3没有二进制的有限表示。最接近的是2054767329987789/2**48=7.3+1/1407374883553280。
看一看http://docs.python.org/tutorial/floatingpoint.html 进一步解释(它在python网站上,但是java和c++有相同的“问题”。)
解决方案取决于您的问题具体是什么:
如果你只是不喜欢看到那些杂音数字,那就修改你的字符串格式。不要显示超过15位有效数字(或7表示浮点)。
如果数字的不精确性破坏了“if”语句,那么应该写if(abs(x-7.3)<容差),而不是if(x==7.3)。
如果你用的是钱,那么你可能真正想要的是十进制定点。存储一个整数,单位是分或任何最小的货币单位。
(不太可能)如果需要超过53个有效位(15-16个有效位)的精度,则使用高精度浮点类型,如bigdecimal。
wi3ka0sx7#
浮点数与实数的不同之处在于,对于任何给定的浮点数,都有一个更高的浮点数。与整数相同。1和2之间没有整数。
无法将1/3表示为浮点数。它下面有个浮子,上面有个浮子,它们之间有一定的距离。三分之一在这个空间里。
apfloat for java声称可以处理任意精度的浮点数,但我从未使用过它。可能值得一看。http://www.apfloat.org/apfloat_java/
在java浮点高精度库之前,这里也提出了类似的问题
q7solyqu8#
看看bigdecimal,它可以处理像这样的浮点运算问题。
新呼叫如下所示:
使用setscale()设置要使用的小数位数精度。
s8vozzvw9#
注意,如果您使用有限精度的十进制算术,并且希望处理1/3,那么您也会遇到同样的问题:0.333333333*3是0.999999999,而不是1.00000000。
不幸的是,5.6、5.8和11.4不是二进制的整数,因为它们包含五分之一。所以它们的浮点表示并不精确,就像0.3333不完全是1/3一样。
如果您使用的所有数字都是非循环小数,并且希望得到精确的结果,请使用bigdecimal。或者正如其他人所说,如果你的价值观和金钱一样,都是0.01或0.001的倍数,或者别的什么,那么把所有的东西乘以10的固定幂,然后使用int或long(加法和减法都很简单:小心乘法)。
但是,如果您对二进制的计算很满意,但是您只想以稍微友好的格式打印出来,请尝试
java.util.Formatter
或者String.format
. 在格式字符串中,指定小于双精度的全精度。对于10位有效数字,比如说,11.3999999999是11.4,因此在二进制结果非常接近只需要几个小数位的值的情况下,结果几乎同样准确,更便于人阅读。指定的精度在某种程度上取决于你对数字所做的运算量——一般来说,你做得越多,累积的误差就越大,但有些算法的累积速度要比其他算法快得多(它们被称为“不稳定”而不是“稳定”的舍入误差)。如果你所做的只是添加一些值,那么我猜只要去掉小数点后一位就可以解决问题。实验。
zzoitvuj10#
正如其他人所指出的,并不是所有的十进制值都可以表示为二进制,因为十进制是基于10的幂,二进制是基于2的幂。
如果精度很重要,请使用bigdecimal,但如果您只是想要友好的输出:
将为您提供:
up9lanfz11#
如果您真的需要精确数学,您可能需要研究使用java的java.math.bigdecimal类。这是一篇来自oracle/sun的关于bigdecimal的好文章。虽然你永远不能像某人所说的那样代表1/3,但你可以决定你想要的结果到底有多精确。setscale()是您的朋友….:)
好吧,因为我现在手头的时间太多了,下面是一个与您的问题相关的代码示例:
为了插入我最喜欢的新语言groovy,这里有一个更简洁的例子:
vxbzzdmp12#
使用bigdecimal。它甚至允许您指定舍入规则(如round\u half\u even,如果两者的距离相同,则舍入到偶数邻居将使统计误差最小化;i、 e.1.5和2.5轮到2)。
hgb9j2n613#
bvjxkvbb14#
正如其他人提到的,您可能希望使用
BigDecimal
类,如果您想得到11.4的精确表示。现在,我们来解释一下为什么会这样:
这个
float
以及double
java中的基本类型是浮点数,其中的数字存储为分数和指数的二进制表示形式。更具体地说,双精度浮点值,例如
double
类型是64位值,其中:1位表示符号(正或负)。
11位表示指数。
52位表示有效数字(小数部分为二进制)。
这些部件结合在一起形成一个整体
double
值的表示。(来源:维基百科:双精度)
有关如何在java中处理浮点值的详细描述,请参阅java语言规范的第4.2.3节:浮点类型、格式和值。
这个
byte
,char
,int
,long
类型是定点数,是数字的精确表示。与定点数字不同,浮点数字有时(可以肯定的是“大多数时间”)无法返回数字的精确表示。这就是为什么你最终11.399999999999
由于5.6 + 5.8
.当需要精确的值时,例如1.5或150.1005,您需要使用一种定点类型,它将能够精确地表示数字。
正如已经多次提到的,java有一个
BigDecimal
类,它将处理非常大的数字和非常小的数字。来自
BigDecimal
班级:不可变的、任意精度的有符号十进制数。bigdecimal由任意精度整数(未标度值)和32位整数标度组成。如果为零或正,则刻度为小数点右侧的位数。如果为负数,则数字的未标度值乘以10,即标度的负数的幂。因此,由bigdecimal表示的数字的值是(unscaledvalue× 10^-比例)。
在堆栈溢出问题上,一直存在着许多与浮点数及其精度有关的问题。以下是可能感兴趣的相关问题列表:
为什么我会看到一个双变量被初始化为21.4这样的值21.399999618530273?
如何在c中打印真正大的数字++
浮点是如何存储的?什么时候重要?
使用浮动或小数作为会计应用程序美元金额?
如果你真的想深入了解浮点数的细节,看看每个计算机科学家都应该知道的浮点数算法。
hrirmatl15#
简而言之:总是使用bigdecimal,并确保您使用的是带string参数的构造函数,而不是双精度参数。
回到您的示例,下面的代码将打印11.4,如您所愿。