IEEE 754个浮点数是谨慎的.

public class MyTest2 {
  public static void main(String[] args) {
    //about 1.00000001490116119384765625E-1 in IEEE-754
    float f = 0.1f;
    //about 1.00000000000000005551115123126E-1 in IEEE-754
    double d = 0.1d;
    System.out.println(String.format("double 0.1= %.30f", d));
    System.out.println(String.format("float 0.1 = %.15f", f));
    System.out.println(d+"");
  }
}

看看这个code run live at IdeOne.com.在JDK8中运行,输出为

double 0.1= 0.100000000000000000000000000000
float 0.1 = 0.100000001490116
0.1

浮点值按预期打印. 我预计双值0.1d会被打印出来,大概是1.0000000000000055511151231260.Why it print all zeros in fraction part

如果我将双变量d转换为字符串,则输出0.1.

System.out.println(d+"");

java如何将最接近的浮点值0.1d(存储为大约1.00000001490116119384765625E-1)转换为精确的0.1?

推荐答案

Java规范要求这种不完美的值显示.f格式只生成与Double.toString(double)方法生成的有效数字一样多的有效数字,然后无意识地添加零以达到所需的精度.

the documentation,对于f格式,如果精度超过Double.toString(double)将产生的小数点后的位数,则"可以附加零以达到精度".这并没有说明这些零被附加到了什么后面.据推测,它们被附加到Double.toString(double)将生成的字符串之后.

The documentation for Double.toString(double)表示,它生成"与唯一区分参数值与类型double的相邻值所需的位数一样多的位数".我会进一步讨论这一点here.对于0.The documentation for Double.toString(double)000000000000005551115123125782702118158340454here5625,Double.toString(double)时会产生"0.1.1".(邻接值、0.09999999999999999167332731531132594682276248931884765625和 0.The documentation for Double.toString(double)00000000000001942890293094023945741355419158935546875,与.1的距离都比0.The documentation for Double.toString(double)000000000000005551115123125782702118158340454here5625远,并且它们的格式分别为"0.09999999999999999"和"0.The documentation for Double.toString(double)00000000000002",因此"0.1"用于唯一地将0.The documentation for Double.toString(double)000000000000005551115123125782702118158340454here5625与其邻居区分开来.)

因此,System.out.println(String.format("double 0.1= %.30f", d))Double.toString(double)的"0.1"开头,并附加29个零.

类似地,如果将d更改为0.099999999999167332731531132594682276248931884765625,String.format将生成"0.099999999999000000000000"——它将获取toString个结果并附加零.对于0.d000000000001942890293094023945741355419158935546875,它产生了"0.d00000000000000200000000000000".

这符合规格.指定的行为不能正确地呈现真值,所以我认为该规范是有缺陷的.

顺便说一句,无论请求的精度是大于还是小于Double.toString(double)将产生的位数,Java规范都很麻烦.在请求权限较小的情况下,the Java specification requires a double rounding可能会增加错误.

Java相关问答推荐

Gmail Javi API批量处理太多请求

在Spring Boot中测试时出现SQL语法错误

无法运行Java(已解决)

使用java访问具体子类特定方法的最佳方法是什么?

扩展到弹出窗口宽度的JavaFX文本字段

DTO到实体,反之亦然,控制器和服务之间的哪一层应该处理转换?

如何找到MongoDB文档并进行本地化?

使用Spring Boot3.2和虚拟线程的并行服务调用

OpenGL ES 3.0-纹理黑色

有效的公式或值列表必须少于或等于255个字符

SpringBoot:在条件{Variable}.isBlank/{Variable}.isEmpty不起作用的情况下进行路径变量验证

组合连接以从两个表返回数据

使用迭代器遍历HashMap不会因IF条件而停止

泛型与泛型问题的完美解决方案?

在Java中将对象&转换为&q;HashMap(&Q)

JXBrowser是否支持加载Chrome扩展?

为什么创建Java动态代理需要接口参数

Kotlin-仅替换字符串中最后一个给定的字符串

错误:JOIN/ON的参数必须是boolean类型,而不是bigint类型.Java Spring启动应用程序

JavaFX中ListView中的问题