浮点数

一、概述

Java虚拟机的浮点数支持符合IEEE0-754 1985浮点标准, 该标准定义了32位和64位浮点数的格式及这些浮点数的运算. 在java虚拟机中, 浮点运算基于32位float类型和64位double类型进行. 每一个执行float类型运算的操作码,都会有一个与之对应的操作码, 该操作码在double类型上实现同样的功能.

浮点数由符号,尾数,基数和指数四部分组成. 符号位的值要么是1,要么是-1, 尾数永远是一个正数, 它确定浮点数的有效位数. 指数指与尾数,符号相乘的基数的幂的值, 幂值可以为正,也可以为负. 可以用以下公式计算: 符号位与尾数相乘, 然后再乘以基数的指数次幂,即得到所指的浮点数.

符号 * 尾数 * 基数的指数次幂

二、规范化指数

因为同一个浮点数可以表示为多个不同的尾数,基数和指数的组合,所以浮点数可以有多种表示形式. 例如, 数字-5 可以被表示为以下所列的几种形式, 这几种形式都是以10为基数.

符号 尾数 基数^指数

-1  50   10^-1

-1  5   10^0

-1  0.5   10^1

-1  0.05   10^2

 

    对于每一个浮点数来说, 都会有一种被称为"规范化"的表示形式. 如果一个浮点数的尾数满足下面所列的关系式,则称这个浮点数为规范化的浮点数.

1/基数 <= 尾数 < 1

在以10为基数的浮点数中, 尾数的小数点位置在第一个不为0的数字的左边. 因此, -5的规范化浮点数表示为: -1 * 0.5 * 10^1. 换句话说, 一个规范化浮点数的尾数, 它的小数点左边的数字一定为0, 紧接小数点右边的数字一定不为0. 不符合这条规则的浮点数被称为非规范化的浮点数. 需要注意的是, 因为0在小数点右边没有不为0的数字, 因此数字0没有规范化的表示. 在处理数字0的时候经常会发出这样的感叹" 为什么要规范化??"

Java虚拟机中浮点数使用2为基数, 因此, 它们可以表示为如下形式:

符号 * 尾数 * 2的指数次幂

Java虚拟机中浮点数的尾数使用二进制来表示. 规范化尾数的二进制小数点(基于二进制与十进制中作用相同)在最高有效非0数字的左边. 因为二进制系统只有两个数字 -- 0和1, 所以, 对于规范化尾数来说, 最高有效的数字就是1.

对于float类型或者double类型来说, 符号位是最高有效位. 尾数在float类型中占最低有效位的23位, 在double类型中占最低有效位的52位. 指数位于符号和尾数之间, 它在float类型中占8位, 在double类型中占11位. float类型的格式如下所示, 符号位表示为s, 指数位表示为e, 尾数位表示为m

31 30~23  22~0

s  eeeeeeee mmmmmmmmmmmmmmmmmmmmmm

符号位为0, 表示正数; 符号位为1, 表示负数. 尾数通常表示为二进制正数.它并不是二进制补码数. 如果符号位为1, 浮点数的值为负, 但是尾数仍然表示为正数, 但是如果要表示浮点数的值,就需要乘上-1.

指数位的解释有三种方式. 指数位全为1, 表示该数为乘法或者减法所产生的特殊值之一 -- 无穷大或者非数字(NaN Not a Number), NaN是某种特殊操作,诸如0除以0的结果, 指数位均为0, 表示该数是一个非规范化浮点数. 其他类型的指数位均表示该数为一个规范化的浮点数.

尾数区域包含一位附加精度位, 它不同于尾数中的其他位的作用. float类型的尾数只占据23位, 但它有24位精度.double类型的尾数占据52位,但它有53位精度. 由于Java虚拟机的浮点数的指数指明该数是否是规范化的, 尾数中的最高有效位是可以预知的,因此没有被划入位数的范围. 如果指数位全为0, 那么该数为非规范化的浮点数, 可知尾数的最高有效位为0. 否则, 浮点数是规范化的,那么尾数的最高有效位为1.