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 类,如果你想得到 11.4 的精确表示。

现在,稍微解释一下为什么会发生这种情况:

floatdouble Java 中的基本类型是 浮点 数字,其中数字存储为分数和指数的二进制表示形式。

更具体地说,双精度浮点值,例如 double type 是一个 64 位值,其中:

  • 1 位表示符号(正或负)。
  • 11 位用于指数。
  • 52 位有效数字(小数部分为二进制)。

这些部分组合起来产生一个 double 值的表示。

(来源: 维基百科:双精度)

有关 Java 中如何处理浮点值的详细说明,请参阅 第 4.2.3 节:浮点类型、格式和值 Java 语言规范。

byte, char, int, long 类型有 固定点 数字,是数字的精确表示。与定点数不同,浮点数有时(可以安全地假设“大多数时间”)无法返回数字的精确表示。这就是你最终得到的原因 11.399999999999 作为结果 5.6 + 5.8.

当需要精确的值(例如 1.5 或 150.1005)时,您将需要使用一种能够精确表示数字的定点类型。

正如已经多次提到的,Java 有一个 BigDecimal 类将处理非常大的数字和非常小的数字。

来自 Java API 参考 BigDecimal 班级:

不可变的,任意推荐的十进制数字。一个大的核心由任意的精确整数未量化值和32位整数量表组成。如果零或正,则尺度是小数点右侧的数字数。如果负数为负,则数字的未量值将乘以十量与量表的否定力量。因此,BigDecimal表示的数字值为(UNSCALEDVALUE×10^-scale)。

Stack Overflow 上有很多与浮点数及其精度相关的问题。以下是您可能感兴趣的相关问题列表:

如果您真的想了解浮点数的具体细节,请看一下 每个计算机科学家都应该了解的浮点运算知识.

其他提示

当输入一个双号,例如,33.33333333333333,将得到的值实际上是最接近表示的双精度值,这正是:

33.3333333333333285963817615993320941925048828125

除以由100给出:

0.333333333333333285963817615993320941925048828125

这也并不表示为一个双精度数,所以再次被四舍五入到最近的表示值,这正是:

0.3333333333333332593184650249895639717578887939453125

当您打印此值时,它就会被四舍五入的再次的17位十进制数字,赠送:

0.33333333333333326

如果你只是要处理的值作为分数,则可以创建其保持分子和分母字段Fraction类。

为附加写入的方法,减,乘,除,以及一个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);
    }
}

}

观察到,你有同样的问题,如果你用有限的精度小数算法,并想处理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或长(加减乘是一切琐碎:注意乘法)

不过,如果你是幸福的二进制进行计算,但你要打印出来的东西在一个稍微友好的格式,尝试java.util.FormatterString.format。在格式字符串指定的精度小于双的全精度。到10个显著附图,比方说,11.399999999999是11.4,因此结果将是几乎准确并且在该二进制结果非常接近,仅需要几个小数的值的情况下更人工可读的。

要指定的精度取决于你有多少数学与你的号码做了一些 - 一般来说你越,越错误会累积,但一些算法积累比别人快很多(它们被称为“不稳定”,而不是‘稳定’相对于舍入误差)。如果你正在做的是增加了一些价值,那么我猜想,仅丢弃一个精确小数位将理清头绪。实验

如果您确实需要精确数学,您可能需要考虑使用 java 的 java.math.BigDecimal 类。这是 Oracle/Sun 的一篇好文章 BigDecimal 的情况. 。虽然你永远无法像有人提到的那样代表 1/3,但你 有权决定您想要的结果的精确程度。setScale() 是你的朋友..:)

好的,因为我现在有太多时间,这里是与您的问题相关的代码示例:

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

敢肯定你可能已经提出,到三线的例子。 :)

如果你想确切的精度,使用的BigDecimal。否则,你可以使用整数乘以你想10 ^无论精度。

正如其他人指出,不是所有的十进制值可以因为小数是基于10和二进制功率是基于二的幂表示为二进制的。

如果精度问题,使用BigDecimal的,但如果你只是想友好的输出:

System.out.printf("%.2f\n", total);

会给你:

11.40

您正在对double类型的精度限制运转起来。

java.math中具有一定的高精度计算设施。

你不能,因为 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) < TOLERANCE) 而不是 if (x == 7.3)。
  • 如果您正在使用金钱,那么您可能真正想要的是十进制定点。存储整数美分或任何货币的最小单位。
  • (非常不可能)如果您需要超过 53 个有效位(15-16 个有效位)的精度,请使用高精度浮点类型,例如 BigDecimal。
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
}

使用java.math.BigDecimal中

双打是二进制小数内部,所以它们有时不能代表小数的确切小数。

乘以100一切,这在很长的存储为美分。

计算机存储数在二进制和实际上不能表示数字如33.333333333或100.0准确。这是关于使用双打棘手的事情之一。你必须圆刚的回答也显示给用户之前。幸运的是,在大多数应用中,你不需要很多小数进不去。

浮点数从实数的不同之处,对于任何给定的浮点数存在下一个更高的浮点数。同为整数。有1和2之间没有整数。

有没有办法来表示1/3为float。有它下面的浮动,有一个浮上面,还有它们之间有一定的距离。和1/3是在该空间中。

Apfloat的Java声称以任意精度浮点数的工作,但我从来没有使用过。也许值得一试。 http://www.apfloat.org/apfloat_java/

有一个类似的问题在这里问前 爪哇浮点高精度库

双打的近似的十进制数的在你的Java源代码。你看到你的源(这是十进制编码)双之间的不匹配(这是一个二进制编码值)的结果。

Java的制造最接近的二进制近似。可以使用java.text.DecimalFormat中显示更好看的十进制值。

使用一个BigDecimal。它甚至可以让你指定舍入的规则(比如ROUND_HALF_EVEN,这将通过四舍五入到相邻的偶数如果两者是相同的距离最小化的统计误差,即1.5和2.5圆至2)。

检查出的BigDecimal,它处理处理浮点运算等的问题。

在新的呼叫是这样的:

term[number].coefficient.add(co);

使用setScale()来设置要使用的小数位精确度的数目。

为什么不从Math类使用round()方法

// 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

如果你有比使用双值以外没有选择,可以使用下面的代码。

public static double sumDouble(double value1, double value2) {
    double sum = 0.0;
    String value1Str = Double.toString(value1);
    int decimalIndex = value1Str.indexOf(".");
    int value1Precision = 0;
    if (decimalIndex != -1) {
        value1Precision = (value1Str.length() - 1) - decimalIndex;
    }

    String value2Str = Double.toString(value2);
    decimalIndex = value2Str.indexOf(".");
    int value2Precision = 0;
    if (decimalIndex != -1) {
        value2Precision = (value2Str.length() - 1) - decimalIndex;
    }

    int maxPrecision = value1Precision > value2Precision ? value1Precision : value2Precision;
    sum = value1 + value2;
    String s = String.format("%." + maxPrecision + "f", sum);
    sum = Double.parseDouble(s);
    return sum;
}

不要使用BigDecimal的浪费efford。在99.99999%的情况下,你不需要它。的java的类型是五言近似的,但在几乎所有情况下,它是足够精确的。记住,您必须在14显著位错误。 这真的是可以忽略不计!

要得到很好的输出使用:

System.out.printf("%.2f\n", total);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top