浮点数的表示

通常,浮点数表示为:

\[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标准,亦没有其他的附加条件,我们应该默认没有隐含位

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

#include

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;

}

Copyright © 2088 波隆网游活动中心 - 热门游戏限时福利聚合站 All Rights Reserved.
友情链接