容易忽视的基础——浮点精度

首先看下下面的题目html

public static void main(String[] args) {
		float a = 1.0f;
		float b = 0.9f;
		float c = 0.8f;
		System.out.println((a-b)==(b-c));
	}
复制代码

请问控制台输出的结果是:java

A. trueapi

B. false安全

不知道各位同窗是怎么选的,换作以前的我确定坚决果断的选择A了。可是,在ide中运行一下后控制台给出的结果是false。为啥呢?bash

浮点精度

浮点型数据类型,FLOAT 数据类型用于存储单精度浮点数或双精度浮点数。浮点数使用 IEEE(电气和电子工程师协会)格式。浮点类型的单精度值具备 4 个字节,包括一个符号位、一个 8 位 excess-127 二进制指数和一个 23 位尾数。尾数表示一个介于 1.0 和 2.0 之间的数。因为尾数的高顺序位始终为 1,所以它不是以数字形式存储的。此表示形式为 float 类型提供了一个大约在 -3.4E+38 和 3.4E+38 之间的范围。--引自百度oracle

实际上咱们的数字都是由2的幂数来凑成的。就如同上面的题目,两个减法得出的结果的二进制类似数是不一样的因此控制台答应出来的结果是false。ide

下面再举个开发过程当中遇到的一个坑ui

class Untitled {
	public static void main(String[] args) {
		float a = 3.01f;
		float b = a % 1.0f;
		System.out.println(b);
	}
}

····
0.00999999
复制代码

没错它不是0.01,取模尽然是0.00999999接近1。因此float的运算是不安全的。那咱们如何保证其计算结果不失真呢?spa

这个时候咱们须要利用BigDecimalcode

class Untitled {
	public static void main(String[] args) {
	BigDecimal a =new BigDecimal("3.01");
    BigDecimal b =new BigDecimal("1");
    float c = a.remainder(b).floatValue();
    System.out.println(c);
	}
}

····
0.01
复制代码

这里用字符串是由于字符串是按位来存储的,天然数都是能够用2进制精确表示的,因此这里使用字符串来实例化。详细能够参考BigDecimal官方文档

相关文章
相关标签/搜索