初学Java时,在关于浮点数的各种资料中都会看到类似的说明:“浮点数在计算时极易产生微小的误差”,“在要求绝对精确的业务场景下,禁止使用浮点数计算”等等。可以做一个最简单的验证:
System.out.println("1-0.9f="+(1-0.9f));
控制台输出:
1-0.9f=0.100000024
本文主要说明两个问题:
- 为什么浮点数在计算中不精确?
- 浮点数的优缺点及应用思路
一、为什么浮点数在计算中不精确?
《The Java® Language Specification(Java语言规范)》JavaSE8版中明确提到,浮点数float和double符合IEEE-754标准的单精度32位和双精度64位格式。
4.2.3. Floating-Point Types, Formats, and Values
The floating-point types are float and double, which are conceptually associated with the single-precision 32-bit and double-precision 64-bit format IEEE 754 values and operations as specified in IEEE Standard for Binary Floating-Point Arithmetic, ANSI/IEEE Standard 754-1985 (IEEE, New York).
Oracle官方文档-《The Java® Language Specification》Java SE 8 Edition
IEEE-754标准文件
- 浮点数的二进制表示
按照IEEE-754标准,以32位浮点数(float)为例,从高位到低位依次为:符号位(1位)+阶码位(8位)+尾数位(23位),实际浮点数值为:
± 尾 数 ∗ 2 阶 码 \pm 尾数*2^{阶码} ±尾