@bombless 在问题的评论里写得没错。IEEE 754最重要的(大家基本上遵守的)是数据的格式。虽然也有算法上的指引(例如有各种rounding mode),但实际上大家实现得不一定那么严格。

C/C++和Java在浮点数运算上规定都比较松。

Java语言上有“FP-strict”的概念。所有浮点数常量表达式和带有strictfp修饰的代码是FP-strict的,而其它浮点数运算默认不是FP-strict的。规定如下:

Java Language Specification, Chapter 15. Expressions, 15.4. FP-strict Expressions

Within an FP-strict expression, all intermediate values must be elements of the float value set or the double value set, implying that the results of all FP-strict expressions must be those predicted by IEEE 754 arithmetic on operands represented using single and double formats.

Within an expression that is not FP-strict, some leeway is granted for an implementation to use an extended exponent range to represent intermediate results; the net effect, roughly speaking, is that a calculation might produce "the correct answer" in situations where exclusive use of the float value set or double value set might result in overflow or underflow.我加黑的部分说的就是默认的、非FP-strict时的运算规定。可见其并不要求严格遵循IEEE 754对单精度和双精度的运算规定。现实来说就是为了容许像x86/x87这样的组合带来的中间运算结果的精度比IEEE 754所规定的高的情况。

C11对浮点类型的规定如下:

The C floating types match the IEC 60559 formats as follows:

— The float type matches the IEC 60559 single format.

— The double type matches the IEC 60559 double format.

— The long double type matches an IEC 60559 extended format,357) else a non-IEC 60559 extended format, else the IEC 60559 double format.

Any non-IEC 60559 extended format used for the long double type shall have more precision than IEC 60559 double and at least the range of IEC 60559 double.(IEC 60559 等价于 IEEE 754)

但实际的C语言实现通常会允许程序员用精度换速度。例如GCC就有很多参数可以指定各种规则要不要遵守:https://gcc.gnu.org/wiki/FloatingPointMath

然后C++嗯,以MSVC为例,它也允许程序员指定运算精度与速度间的取舍:Microsoft Visual C++ Floating-Point Optimization

在x86/x87环境中进行浮点数运算,如果在x87用默认精度(扩展双精度,也就是80-bit的浮点数格式)上连续做超过1次运算而不对中间结果做调整,那它的精度就会比IEEE 754的双精度要高,运算结果自然就不完全一样了。这只是一个例子,能让浮点数运算与“预期”不一样的因素挺多,例如换换顺序、折叠一下常量啥的…

我们在实现HotSpot JVM的时候在非FP-strict的地方基本上只要保证解释器跟JIT编译器对一些特定Math浮点数方法返回的结果足够接近就好了…

-----------------------

来再geek一点吧。

Java语言规范说浮点数字面量转换到浮点类型数值的算法由 java.lang.Double.valueOf(String) 方法的文档规定。而后者指定使用IEEE 754的round-to-nearest模式来转换。

Java里,

0.01d + 0.05d是一个常量表达式,由语言规范规定必须做常量折叠。这个常量折叠是FP-strict的。

根据规范,把字面量转换为Java认知的double,

0.01d:

十六进制:

3f847ae147ae147b二进制:

0 01111111000 0100011110101110000101000111101011100001010001111011十进制:

0.01000000000000000020816681711721685132943093776702880859375

0.05d:

十六进制:

3fa999999999999a二进制:

0 01111111010 1001100110011001100110011001100110011001100110011010十进制:

0.05000000000000000277555756156289135105907917022705078125

(懒人提示:要看一个Java double的准确十进制表示,只要

new BigDecimal(x).toString()就好了…)

可见这两个数字在double格式都无法准确表示,而只能用近似值。

这两个浮点数相加的结果是:

二进制:

0 01111111010 1110101110000101000111101011100001010001111010111001十进制:

0.060000000000000004718447854656915296800434589385986328125

然后Java的formatter(java.text.DecimalFormat)在把这个double转换为字符串的时候,它并不追求把数字的真实值准确转换出来,而是更追求转换速度,所以会看情况round一下…所以楼主会看到类似 6.0000000000000005E-2 这样的字符串表示。

题主可以试试看不写0.01d+0.05d,而直接写0.06d然后试试把它输出成字符串看看。你会看到它其实也不是精确值,而是

0.059999999999999997779553950749686919152736663818359375,而Java的DecimalFormat即便用

"0.0000000000000000000000000000000000000000000000E0"的格式也会把它格式化成

6.0000000000000000000000000000000000000000000000E-2嗯挺迷惑人的。

而楼主用的C的环境多半在格式化字符串的时候用了别的取舍所以多看到了一位…

java 浮点数运算_对于同样的浮点数运算为何 Java 与 C 的结果不相同?相关推荐

  1. java 清空控制台_利用原生库和JNI(Java原生接口)实现H2数据库漏洞利用

    在H2数据库引擎中获取代码执行权限的技术早已是众所周知,但有个要求就是H2能够动态编译Java代码.而本文将向大家展示以前没有公开过的利用H2的方法,并且无需使用Java编译器,即通过原生库和JNI( ...

  2. 加减法叫做什么运算_期中备考:数学运算定律、法则与顺序

    很多孩子的数学不好,尤其是女孩子.家长往往认定为数学不好就是孩子不擅长,能力差.其实未必,有的孩子数学不好的原因并不在于智商,而是没有理解到数学的方法与逻辑,比如小学的运算中,很多孩子并没有了解到运算 ...

  3. java框架核心技术_你必须掌握的 21 个 Java 核心技术!(干货)

    点击上方"java进阶架构师",选择右上角"置顶公众号" 20大进阶架构专题每日送达 51闲来无事,师长一向不(没)喜(有)欢(钱)凑热闹,倒不如趁着这时候复盘 ...

  4. java oom分析_作为测试你应该知道的JAVA OOM及定位分析

    上周现网一个内存溢出问题导致应用服务器每隔一小时死一次,遂整理下常见的OMM.发现方法和处理方式,加入Bug预防. 常见的OutOfMemoryError有三种:OutOfMemoryError:Pe ...

  5. java gradle构建_在Gradle中为JPMS构建Java 6-8库

    java gradle构建 通过提供Java 9 module-info.class了解如何使用Gradle构建支持JPMS( Java平台模块系统 )的Java 6-8库. 介绍 如果您需要JPMS ...

  6. java转换为c#_将25k行C#转换为Java的经验教训

    java转换为c# 由于各种原因,我最近完成了一个将复杂的财务应用程序从C#转换为Java的项目. 港口的原因大部分是非技术性的,而是对相关企业的一项战略举措. 这是一次有趣的经历,我在此过程中吸取了 ...

  7. java方法重载_在Python中该如何实现Java的重写与重载

    前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:清风python PS:如有需要Python学习资料的小伙伴可以加点击 ...

  8. java future用法_你必须掌握的 21 个 Java 核心技术

    作者:工程师-搁浅来源:https://www.jb51.net/article/122070.htm 写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,主要是和一些java基础知 ...

  9. java初学者书籍_面向初学者的5本最佳Java核心书籍

    java初学者书籍 Today I am sharing the best java books to learn java programming. Java is one of the most ...

  10. java hashmap用法_备战金九银十:Java核心技术面试题100+,助你搞定面试官

    一线互联网公司工作了几年,我作为求职者参加了不少面试,也作为面试官面试了很多同学,整理这份面试指南,一方面是帮助大家更好的准备面试,有的放矢,另一方面也是对自己知识框架做一个体系化的梳理. 这篇文章梳 ...

最新文章

  1. 如何设计一个深度学习项目
  2. 009_logback本地Appender
  3. 布道微服务_04服务的注册与发现
  4. 文本挖掘预处理:向量化与Hash Trick
  5. Dubbo注解版配置
  6. 操作系统——磁盘寻道练习题及答案
  7. 【渝粤教育】广东开放大学 电路分析基础 形成性考核 (59)
  8. java结构设计_Java基本的程序设计结构(一)
  9. NOIP1996复赛 普及组 第二题 python
  10. VC realize the transparent windows
  11. centos7的网卡配置 实用经典总结
  12. Bootstrap学习(一)
  13. 剑指Offer之复杂链表的复制
  14. Thread-Specific Storage Pattern
  15. 最薄翻转笔记本 联想Yoga13-IFI 6700
  16. 机器认知、人机交互、边缘计算……在这里,他们谈论了关于AI的关键议题...
  17. ecshop模板修改大全
  18. android lut格式文件下载,一键调色?教你用Lut直接调出电影色调(内含下载)
  19. 服务器麒麟系统是arm还是x64,麒麟arm环境安装ceph
  20. VS用SSIS实现SQL Server数据库与Excel表格数据的相互导入

热门文章

  1. Entity Framework Core——9.日志记录与拦截器
  2. data参数 layui_layui ajax传参的data类型
  3. 解决win10 home edition升级17074后virtualbox蓝屏(绿屏)无法运行的问题
  4. 挺难过的,测完后发现自已有点色盲--色盲、色弱测试图
  5. 中国色盲眼镜行业需求态势与应用前景预测报告(新版)2022-2027
  6. 【Nginx 日志配置】【访问日志log_format】【错误日志error_log 指令】【Nginx的日志轮转】
  7. 外贸业务数据BI可视化分析
  8. mysql日期用什么类型_mysql存储日期使用什么类型
  9. 电视剧《Prison Break(越狱)》真的很不错,多少年没有这么经典的节目了,风靡全球啊。。。...
  10. TCP accept返回的socket会在服务端新开一个端口嘛?服务端TCP连接数限制