在Java中使用double保持精度

在Java中使用double保持精度,java,floating-point,double,precision,Java,Floating Point,Double,Precision,上述代码打印: 11.399999999 我怎样才能把它打印出来(或者可以用作)11.4?将所有内容乘以100,然后以美分的形式存储起来。非常确定您可以将其制作成一个三行示例。:) 如果您想要精确的精度,请使用BigDecimal。否则,可以使用整数乘以10^的任意精度。double是Java源代码中十进制数的近似值。您看到了double(二进制编码的值)和源代码(十进制编码的)之间不匹配的结果 Java正在生成最接近的二进制近似值。您可以使用java.text.DecimalFormat来显

上述代码打印:

11.399999999

我怎样才能把它打印出来(或者可以用作)11.4?

将所有内容乘以100,然后以美分的形式存储起来。

非常确定您可以将其制作成一个三行示例。:)

如果您想要精确的精度,请使用BigDecimal。否则,可以使用整数乘以10^的任意精度。

double是Java源代码中十进制数的近似值。您看到了double(二进制编码的值)和源代码(十进制编码的)之间不匹配的结果


Java正在生成最接近的二进制近似值。您可以使用java.text.DecimalFormat来显示外观更好的十进制值。

使用BigDecimal。它甚至可以让您指定舍入规则(如ROUND_HALF_even,如果两者的距离相同,则通过舍入到偶数邻居来最小化统计误差;即1.5和2.5都舍入到2)。

注意,如果使用有限精度的十进制算法,您也会遇到同样的问题,并且想要处理1/3:0.333333*3是0.99999999,而不是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.399999999是11.4,因此,如果二进制结果非常接近只需要几个小数位的值,那么结果几乎同样准确,更容易让人阅读


指定的精度在一定程度上取决于您对数字所做的计算量——通常,您做的越多,累积的错误就越多,但某些算法的累积速度要比其他算法快得多(它们被称为“不稳定”而不是“稳定”的舍入错误)。如果您所做的只是添加一些值,那么我猜只需删除精度的小数点后一位就可以解决问题。实验。

正如其他人所提到的,如果您想获得11.4的精确表示,您可能需要使用该类

现在,我们来解释一下为什么会发生这种情况:

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

更具体地说,双精度浮点值(如
double
类型)是64位值,其中:

  • 1位表示符号(正或负)
  • 指数为11位
  • 52位表示有效数字(小数部分为二进制)
这些部分组合在一起,生成值的
表示

(来源:)

有关如何在Java中处理浮点值的详细说明,请参阅Java语言规范的

byte
char
int
long
类型都是数字,它们是数字的精确表示。与定点数字不同,浮点数字有时(可以安全地假设“大部分时间”)无法返回数字的精确表示形式。这就是为什么在
5.6+5.8
的结果中,最终得到
11.399999999

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

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

BigDecimal
类的Java API参考中:

一成不变, 任意精度有符号十进制 数字。BigDecimal由一个 任意精度整数无标度 值和32位整数刻度。如果 零或正,刻度为 文本右侧的位数 小数点。如果为负数,则为 数字的未标度值为 乘以10,等于 规模的否定。价值 由 因此,BigDecimal是(非标度值 ×10^-比例)

关于堆栈溢出,有许多问题与浮点数及其精度有关。以下是可能感兴趣的相关问题列表:


如果您真的想深入了解浮点数的细节,请看一看。

正如其他人所指出的,并不是所有的十进制值都可以表示为二进制,因为十进制是基于10的幂,二进制是基于2的幂

如果精度很重要,请使用BigDecimal,但如果您只是想要友好的输出:

public class doublePrecision {
    public static void main(String[] args) {

        double total = 0;
        total += 5.6;
        total += 5.8;
        System.out.println(total);
    }
}
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);
    }
}

}
将为您提供:

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

看看BigDecimal,它处理类似于浮点运算的问题

新呼叫将如下所示:

11.40

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

使用java.math.BigDecimal


double在内部是二进制分数,因此它们有时不能将十进制分数表示为精确的十进制。

您不能,因为7.3没有二进制的有限表示。最接近的是20547673729987789/2**48
33.3333333333333285963817615993320941925048828125
0.333333333333333285963817615993320941925048828125
0.3333333333333332593184650249895639717578887939453125
0.33333333333333326
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


    }
}
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 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);
    }
}

}
System.out.printf("%.2f\n", total);
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
}
// 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;
}
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);
    }
}
        /*
        0.8                     1.2
        0.7                     1.3
        0.7000000000000002      2.3
        0.7999999999999998      4.2
        */
        double adjust = fToInt + 1.0 - orgV;
        
        // The following two lines works for me. 
        String s = String.format("%.2f", adjust);
        double val = Double.parseDouble(s);

        System.out.println(val); // output: 0.8, 0.7, 0.7, 0.8