浮点数的表示
通常,浮点数表示为:
\[N = (-1)^{S} \times M \times R^{E} \]其中,S取值为0或者1,用来决定浮点数的符号;M是一个二进制定点小数,称为尾数,一般用定点原码小数表示;E是一个二进制顶点整数,称为阶码或者指数,用移码表示。R是基数(隐含),可以约定为2、4、16等
浮点数的表示范围
原码是关于原点对称的,故浮点数的范围也是关于原点对称的,如图2.10所示
- 运算结果大于最大正数时称为正上溢,小于绝对值最大负数时称为负上溢,正上溢和负上溢统称上溢。数据一旦产生上溢,计算机必须中断运算操作,进行溢出处理。
- 当运算结果在0至最小正数之间时称为正下溢,在0至绝对值最小负数之间时称为负下溢,正下溢和负下溢统称下溢。数据下溢时,浮点数值趋于零,计算机将其当作机器零处理。
浮点数的规格化
为了在浮点数运算过程中尽可能多地保留有效数字的位数,使有效数字尽量占满尾数数位,必须在运算过程中对浮点数进行规格化操作。所谓规格化操作,是指通过调整一个非规格化浮点数的尾数和阶码的大小,使非零浮点数在尾数的最高数位上保证是一个有效值。
-
左规:当运算结果的尾数的最高数位不是有效位,即出现 \(\pm\) 0.0...0x...x的形式时,需要进行左规。左规时,尾数每左移一位、阶码减1(基数为2时)。左规可能要进行多次。
-
右规:当运算结果的尾数的有效位进到数点前面时,需要进行右规,右规只需进行一次。将尾数右移一位、阶码加1(基数为2时)。规时,阶码增加可能导致溢出。
IEEE754标准
单精度格式中包含 1 位符号 s、8 位阶码e和 23 位尾数,:双精度格式包含1位符号 s、11位阶码e和 52 位尾数 1。基数隐含为2:尾数用原码表示。对于规格化的二进制浮点数,尾数的最高位总是 1,为了能使尾数多表示一位有效位,将这个1隐藏,称为隐藏位,因此 23 位尾数实际表示了 24 位有效数字。IEEE 754 规定隐藏位1的位置在小数点之前,例如,\((12)_{10} = (1100)_{2}\),将它规格化后结果为 \(1.1 \times 2^{3}\),其中整数部分的“1”将不存储在 23 位尾数内。
单精度与双精度浮点数都采用隐藏尾数最高位的方法,因而使浮点数的精度更高。
在 IEEE 754 标准中,指数用移码表示,但偏置值并不是通常n位移码所用的\(2^{n-1}\),而是 \(2^{n-1}-1\)因此,单精度和双精度浮点数的偏置值分别为 127 和 1023。在存储浮点数阶码之前,偏置值要先加到阶码真值上。
所以,在IEEE754标准中,规格化单精度浮点数的真值为:
\[(-1)^{s} \times 1.f \times 2^{e-127} \]规格化双精度浮点数的真值为
\[(-1)^{s} \times 1.f \times 2^{e-1023} \]浮点数能表示的范围
这个表的意思应该是绝对值的最大值与最小值
阶码为全0或者全1时的特殊意义
定点、浮点表示的区别
-
数值的表示范围
- 若定点数和浮点数的字长相同,则浮点表示法所能表示的数值范围远大于定点表示法。
-
精度
- 虽然扩大了数的表示范围,但精度降低了。对于字长相同的定点数和浮点数来说,精度却降低了
-
数的运算
- 浮点数包括阶码和尾数两部分,运算时不仅做尾数的运算,还要做阶码的运算,而且运算结果要求规格化,所以浮点运算远比定点运算复杂
-
溢出问题
- 在定点运算中,当运算结果超出数的表示范围时,发生溢出;在浮点运算中,运算结果超出尾数表示范围却不一定溢出,只有规格化后阶码超出所能表示的范围时,才发生溢出。
浮点数的机器数
最后我们附上一个将浮点数转为二进制的C++程序,结合真值来看,可以对浮点数的编码有更好的理解
#include <iostream>
#include <bitset>
int main() {
float num;
std::cout << "Please enter a floating-point number: ";
std::cin >> num;
union FloatInt {
float f;
unsigned int i;
} data;
data.f = num;
// Using union to access the internal representation of the floating-point number
std::cout << "The machine representation of the floating-point number " << num << " (in hexadecimal): "
<< std::hex << data.i << std::endl; // Print the hexadecimal form
// Convert the integer to a 32-bit binary string
std::bitset<32> binaryRepresentation(data.i);
std::string binaryString = binaryRepresentation.to_string();
// Splitting into sign, exponent, and mantissa parts
std::string sign = binaryString.substr(0, 1);
std::string exponent = binaryString.substr(1, 8);
std::string mantissa = binaryString.substr(9, 23);
// Printing the sign, exponent, and mantissa separately
std::cout << "The machine representation of the floating-point number " << num << " (in binary): "
<< sign << ";" << exponent << ";" << mantissa << std::endl;
return 0;
}
标签:阶码,运算,尾数,浮点数,times,理解,深入,规格化
From: https://www.cnblogs.com/AH20/p/18473990