文章目录
1 浮点数的内存表示
1.1 内存中的浮点数
浮点数在内存中的存储方式为:符号位、指数、尾数。
float和double类型的数据在计算机内部的表示方法是相同的,但由于所占存储空间的不同,其分别能够表示的数值范围和精度不同。
浮点数的特殊情况:
1.2 浮点数的转换
浮点数的转换步骤:
- 将浮点数转换成二进制。
- 用科学计数法表示二进制浮点数。
- 计算指数偏移后的值。
注意:计算指数时需要加上偏移量,而偏移量的值与类型有关。
对于指数6,偏移后的值如下:
- float:127 + 6 ⇒ 133
- double:1023 + 6 ⇒ 1029
转换示例:
通过unsigned int类型的指针将浮点数的内存表示打印出来:
#include <stdio.h>
int main()
{
float f = 8.25;
unsigned int* p = (unsigned int*)&f;
printf("0x%08X\n", *p);
return 0;
}
1.3 浮点数的不连续
思考:int和float都占4个字节的内存,为什么float却比int的范围大的多呢?
浮点类型的特点:
- float能表示的具体数字的个数与int相同。
- float可表示的数字之间不是连续的,存在间隙。
- float只是一种近似的表示法,不能作为精确数使用。
- 由于内存表示法相对复杂,float的运算速度比int慢得多。
注意:double与float具有相同的内存表示法,因此double也是不精确的。由于double占用的内存较多,所能表示的精度比float高。
1.4 浮点数的大数吃小数问题
浮点数的加法需要先对阶,再计算,以0.5加0.125为例,计算过程如下:
我们可以看到在对阶的过程中,当大数比小数大很多时(大概是1600万倍时),小数由于右移而导致全部数据移出变为0。
2 浮点数据输出控制和精度
2.1 浮点数据的输出控制
#include<iostream>
#include<Windows.h>
using namespace std;
int main(void){
double value = 12.3456789;
// 默认精度是6,所以输出为 12.3457
//(默认情况下,精度是指总的有效数字)
cout << value << endl;
// 把精度修改为4, 输出12.35, 对最后一位四舍五入
// 精度修改后,持续有效,直到精度再次被修改
cout.precision(4);
cout << value << endl;
// 使用定点法, 精度变成小数点后面的位数
// 输出12.3457
cout.flags(cout.fixed);
cout << value << endl;
// 定点法持续有效
// 输出3.1416
cout << 3.1415926535 << endl;
// 把精度恢复成有效数字位数
cout.unsetf(cout.fixed);
cout << value << endl; //输出12.35
cout << 3.1415926535 << endl; //输出3.142
system("pause");
return 0;
}
2.2 浮点数据的精度
#include <Windows.h>
#include <iostream>
using namespace std;
int main()
{
float f = 0.123456789f;
double d = 0.123456789123456789;
cout.precision(9);
cout.flags(cout.fixed); //输出0.123456791,float类型的数据精度为7位
cout << f << endl;
cout.precision(18); //输出0.123456789123456784,double类型的精度为16位(测出来17位,巧合?)
cout << d << endl;
system("pause");
return 0;
}
参考资料: