java中带double的浮点保留精度

imzjd6km  于 2021-06-30  发布在  Java
关注(0)|答案(22)|浏览(390)
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使用)?

bprjcwpo

bprjcwpo1#

把所有的东西都乘以100,然后储存在一个很长的分币里。

5f0d552i

5f0d552i2#

很确定你可以把它变成一个三行的例子。:)
如果您想要精确的精度,请使用bigdecimal。否则,可以使用int乘以10^的任意精度。

mqxuamgl

mqxuamgl3#

为什么不使用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
2lpgd968

2lpgd9684#

不要用大小数浪费你的精力。99.99999%的情况下你不需要它。java double类型是cource a

1tuwyuhd

1tuwyuhd5#

如果除了使用双值之外别无选择,可以使用下面的代码。

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

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。

wi3ka0sx

wi3ka0sx7#

浮点数与实数的不同之处在于,对于任何给定的浮点数,都有一个更高的浮点数。与整数相同。1和2之间没有整数。
无法将1/3表示为浮点数。它下面有个浮子,上面有个浮子,它们之间有一定的距离。三分之一在这个空间里。
apfloat for java声称可以处理任意精度的浮点数,但我从未使用过它。可能值得一看。http://www.apfloat.org/apfloat_java/
在java浮点高精度库之前,这里也提出了类似的问题

q7solyqu

q7solyqu8#

看看bigdecimal,它可以处理像这样的浮点运算问题。
新呼叫如下所示:

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

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

s8vozzvw

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,因此在二进制结果非常接近只需要几个小数位的值的情况下,结果几乎同样准确,更便于人阅读。
指定的精度在某种程度上取决于你对数字所做的运算量——一般来说,你做得越多,累积的误差就越大,但有些算法的累积速度要比其他算法快得多(它们被称为“不稳定”而不是“稳定”的舍入误差)。如果你所做的只是添加一些值,那么我猜只要去掉小数点后一位就可以解决问题。实验。

zzoitvuj

zzoitvuj10#

正如其他人所指出的,并不是所有的十进制值都可以表示为二进制,因为十进制是基于10的幂,二进制是基于2的幂。
如果精度很重要,请使用bigdecimal,但如果您只是想要友好的输出:

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

将为您提供:

11.40
up9lanfz

up9lanfz11#

如果您真的需要精确数学,您可能需要研究使用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
vxbzzdmp

vxbzzdmp12#

使用bigdecimal。它甚至允许您指定舍入规则(如round\u half\u even,如果两者的距离相同,则舍入到偶数邻居将使统计误差最小化;i、 e.1.5和2.5轮到2)。

hgb9j2n6

hgb9j2n613#

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

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中打印真正大的数字++
浮点是如何存储的?什么时候重要?
使用浮动或小数作为会计应用程序美元金额?
如果你真的想深入了解浮点数的细节,看看每个计算机科学家都应该知道的浮点数算法。

hrirmatl

hrirmatl15#

简而言之:总是使用bigdecimal,并确保您使用的是带string参数的构造函数,而不是双精度参数。
回到您的示例,下面的代码将打印11.4,如您所愿。

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

相关问题