JAVA-DIY-9-WEEK

Persistence is not necessarily successful, but not sure will not succeed.

Posted by Hyuga on May 12, 2019

第9次讨论主题:浮点数

MIN_VALUE和MIN_NORMAL

包装类Float中为什么有两个常量来表示最小值:MIN_VALUE和MIN_NORMAL?

活到老学到老。以前都没注意过浮点型包装类中竟然有两个最小值,只知道有min_value.

看了jdk描述如下:

static float MIN_VALUE

  • 保存float类型数据的最小正非零值的常量,即2^-149。
  • 它等于十六进制的浮点字面值 0x0.000002P-126f,也等于 Float.intBitsToFloat(0x1)。
  • 输出结果为:1.4E-45

static float MIN_NORMALE

  • 保存 float 类型数据的最小正标准值的常量,即2^-126。
  • 它等于十六进制的浮点字面值 0x1.0p-126f,也等于 Float.intBitsToFloat(0x00800000)。
  • 输出结果为:1.17549435E-38

区别:

  1. MIN_VALUE表示的数据范围比MIN_NORMALE表示的数据范围更大。
  2. MIN_VALUE是最小正非0值常量,MIN_NORMALE是最小正标准值常量。

引用维基百科描述

【IEEE二进制浮点数算术标准】(IEEE 754)是20世纪80年代以来最广泛使用的浮点数运算标准,为许多CPU与浮点运算器所采用。

一个浮点数的实际值,等于符号位(sign bit)乘以指数偏移值(exponent bias)再乘以分数值(fraction)。

其中有规约形式的浮点数和非规约形式的浮点数两种标准。

规约形式:“规约”是指用唯一确定的浮点形式去表示一个值。由于这种表示下的尾数有一位隐含的二进制有效数字,为了与二进制科学计数法的尾数(mantissa)相区别,IEEE754称之为有效数(significant)。

举例来说,双精度 (64-bit) 的规约形式浮点数在指数偏移值的值域为 {00000000001} {00000000001} (11-bit) 到 {11111111110} {11111111110},在分数部分则是 {000…..000} {000…..000}到 {111…..111} {111…..111} (52-bit)

非规约形式:非规约形式的浮点数的指数偏移值比规约形式的浮点数的指数偏移值小1。例如,最小的规约形式的单精度浮点数的指数部分编码值为1,指数的实际值为-126;而非规约的单精度浮点数的指数域编码值为0,对应的指数实际值也是-126而不是-127。实际上非规约形式的浮点数仍然是有效可以使用的,只是它们的绝对值已经小于所有的规约浮点数的绝对值;即所有的非规约浮点数比规约浮点数更接近0。规约浮点数的尾数大于等于1且小于2,而非规约浮点数的尾数小于1且大于0。

除了规约浮点数,IEEE754-1985标准采用非规约浮点数,用来解决填补绝对值意义下最小规格数与零的距离。

所以包装类Float中之所以会有MIN_VALUE和MIN_NORMAL两个常量来表示最小值,是符合IEEE 754中对于规约浮点数和非规约浮点数的标准。

`````

精度问题

double a = 1.0-0.9的结果不精确等于0.1,为什么?

IEEE中有说明,计算机使用浮点数运算的主因,是因为计算机使用的是二进位制的运算。由于十进位制无法准确换算成二进位制的部分小数,如0.1,因此只能使用近似值的方式表达。