public class doublePrecision {
public static void main(String[] args) {
double total = 0;
total += 5.6;
total += 5.8;
System.out.println(total);
}
}
上面的代码输出:
11.399999999999
如何使其只打印(或者能够使用它作为) 11.4?
public class doublePrecision {
public static void main(String[] args) {
double total = 0;
total += 5.6;
total += 5.8;
System.out.println(total);
}
}
上面的代码输出:
11.399999999999
如何使其只打印(或者能够使用它作为) 11.4?
BigDecimal
类。float
和double
是浮点数的原始类型,其中数字以二进制的形式存储为分数和指数的表示。double
类型)是一个64位的值,其中:double
值的表示。byte
、char
、int
、long
类型是定点数,它们是数字的精确表示。与定点数不同,浮点数有时(可以安全地假设是“大多数情况下”)无法返回数字的精确表示。这就是为什么5.6 + 5.8
的结果会变成11.399999999999
的原因。BigDecimal
类,可以处理非常大和非常小的数字。BigDecimal
类的定义:
在Stack Overflow上有很多关于浮点数及其精度的问题。以下是一些相关问题的列表,可能会引起您的兴趣:不可变的、任意精度的有符号十进制数。BigDecimal由一个任意精度的整数无标度值和一个32位整数标度组成。如果为零或正数,则标度是小数点右侧的数字位数。如果为负数,则数字的无标度值乘以10的标度的负数次幂。因此,BigDecimal所表示的数字的值为(无标度值×10^-标度)。
如果你真的想深入了解浮点数的细节,可以看看《每个计算机科学家都应该了解的浮点数算术》。
BigDecimal
比double
慢得多,但它并不需要,因为double
具有15位小数的精度,您只需要四舍五入即可。 - Peter Lawrey当你输入一个double类型的数字,例如33.33333333333333
,实际上得到的值是最接近的可以表示为双精度浮点数的值,该值正好是:
33.3333333333333285963817615993320941925048828125
将其除以100得:
0.333333333333333285963817615993320941925048828125
这也不能表示为双精度数字,所以它再次四舍五入到最接近的可表示值,其值正好是:
0.3333333333333332593184650249895639717578887939453125
当你将这个值打印出来时,它会再次四舍五入保留17位小数,结果为:
0.33333333333333326
如果你只想将值处理为分数,你可以创建一个包含分子和分母字段的Fraction类。
编写add、subtract、multiply和divide方法以及toDouble方法。这样,在计算过程中可以避免使用浮点数。
编辑:快速实现如下,
public class Fraction {
private int numerator;
private int denominator;
public Fraction(int n, int d){
numerator = n;
denominator = d;
}
public double toDouble(){
return ((double)numerator)/((double)denominator);
}
public static Fraction add(Fraction a, Fraction b){
if(a.denominator != b.denominator){
double aTop = b.denominator * a.numerator;
double bTop = a.denominator * b.numerator;
return new Fraction(aTop + bTop, a.denominator * b.denominator);
}
else{
return new Fraction(a.numerator + b.numerator, a.denominator);
}
}
public static Fraction divide(Fraction a, Fraction b){
return new Fraction(a.numerator * b.denominator, a.denominator * b.numerator);
}
public static Fraction multiply(Fraction a, Fraction b){
return new Fraction(a.numerator * b.numerator, a.denominator * b.denominator);
}
public static Fraction subtract(Fraction a, Fraction b){
if(a.denominator != b.denominator){
double aTop = b.denominator * a.numerator;
double bTop = a.denominator * b.numerator;
return new Fraction(aTop-bTop, a.denominator*b.denominator);
}
else{
return new Fraction(a.numerator - b.numerator, a.denominator);
}
}
}
numerator
和 denominator
定义为 int
类型,为什么需要浮点精度呢? - Samir Talwar请注意,如果您使用有限精度的十进制算术,并且想处理1/3,则会遇到同样的问题:0.333333333 * 3不是1.00000000,而是0.999999999。
不幸的是,5.6、5.8和11.4在二进制中并不是圆整数,因为它们涉及到五分之一。所以它们的浮点表示不是准确的,就像0.3333不是完全等于1/3一样。
如果您使用的所有数字都是不重复的小数,并且希望得到精确结果,请使用BigDecimal。或者像其他人所说的那样,如果您的值类似于货币,因为它们都是0.01或0.001或其他的倍数,则将所有内容乘以固定的10的幂,并使用int或long(加法和减法很简单:小心乘法)。
然而,如果您对计算使用二进制感到满意,但只想以稍微友好的格式打印出结果,请尝试使用java.util.Formatter
或String.format
。在格式字符串中指定小于double的完整精度的精度。例如,对于10个有效数字,11.399999999999是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
您遇到了类型 double 的精度限制。
Java.Math 提供了一些任意精度算术工具。
我相信你可以把这个例子简化成三行代码。
如果您需要精确计算,请使用BigDecimal。否则,您可以使用整数乘以10 ^所需的精度。
正如其他人所指出的,不是所有的十进制值都可以表示为二进制,因为十进制是基于10的幂,而二进制是基于2的幂。
如果精度很重要,请使用BigDecimal,但如果你只想要友好的输出:
System.out.printf("%.2f\n", total);
我会为您提供:
11.40
private void getRound() {
// this is very simple and interesting
double a = 5, b = 3, c;
c = a / b;
System.out.println(" round val is " + c);
// round val is : 1.6666666666666667
// if you want to only two precision point with double we
// can use formate option in String
// which takes 2 parameters one is formte specifier which
// shows dicimal places another double value
String s = String.format("%.2f", c);
double val = Double.parseDouble(s);
System.out.println(" val is :" + val);
// now out put will be : val is :1.67
}