public static void main(String[] args) { double a = 0.1; double b = 0.7; System.out.println(a+b); // 0.7999999999999999 System.out.println((int)(a+b)); // 0 System.out.println((int)((a+b)*10)); // 7 }
Java 虚拟机规范要求虚拟机实现在处理浮点数时,必须严格遵循 IEEE754 规范中所规定的行为和限制(摘自 jvms10)。
The floating-point types are float and double, which are conceptually associated with the 32-bit single-precision and 64-bit double-precision format IEEE 754 values and operations as specified in IEEE Standard for Binary Floating-Point Arithmetic (ANSI/IEEE Std. 754-1985, New York).
简单说说 IEEE 754
单精度,32 bits
S 为符号位,1 表示 负数,0 表述正数。
- exp 表示阶码,在计算机用移码表示 ,便用浮点数加减运算时进行对阶操作。其取值为 [1, 254],本来是 [0, 255],但最高位和最低位保留作为特殊值处理 ,±0 ,±∞。
- frac 表示小数部分,其取值 [1.0, 2.0) ,其中 1.xxx 中整数部分的 1 默认省略不写,这样还可以多存一位,提高精度,所以有尾数精度 = 尾数位数 + 1。
IEEE754 标准定义的浮点格式参数
特殊值的表示
浮点数加法
具体推算
//------------------------------0.1------------------------------------ //0.0001100110011001100110011001100110011001100110011001 1001 - //1.1001100110011001100110011001100110011001100110011001E-4 - // 阶码部分 -4+1023=1019 01111111011 - // 0 01111111011 1001100110011001100110011001100110011001100110011001 - // 0-01111111011-1001100110011001100110011001100110011001100110011001 - //------------------------------0.1------------------------------------ //------------------------------0.7------------------------------------ //0.1011001100110011001100110011001100110011001100110011 0 - //1.0110011001100110011001100110011001100110011001100110E-1 - // 阶码部分 -1+1023=1022 01111111110 - // 0 01111111110 0110011001100110011001100110011001100110011001100110 - // 0-01111111110-0110011001100110011001100110011001100110011001100110 - //------------------------------0.7------------------------------------ //------------------------------对阶后相加------------------------------------ // 0.0011001100110011001100110011001100110011001100110011001E-1 - // + 1.0110011001100110011001100110011001100110011001100110000E-1 - // __________________________________________________________________________ // 1.1001100110011001100110011001100110011001100110011001001 (尾数部分) - // 规格化 - // 0-01111111110-1001100110011001100110011001100110011001100110011001 - // 二进制转十进制 - // 0.79999999999999993338661852249060757458209991455078125 - // 0.7999999999999999 - //------------------------------对阶后相加------------------------------------
特别说明:文中的部分截图来自国防科技大学(中国大学慕课MOOC )和 卡耐基梅隆大学 计算机原理课程截图和。
特别推荐:二进制在线转换
特别吐槽:csdn 富文本编辑器真心不好用 ~