1. 浮点型
1.1 C++中有三种浮点类型
- 按照精度的不同划分如下:
(1)float: 单精度类型
(2)double: 双精度类型
(3)long double: 长双精度类型
1.2 各种浮点型占用字节数
各种浮点型占用字节数列表
数据类型 字节数 位数 十进制有效位数 阶码 尾数 float 4 32 7位 8位 23位 double 8 64 15位 11位 52位 long double 10 80 19位 15位 64位 注:double消耗的内存是float的2倍,double的运算速度比float慢得多,所以能用float解决能满足有效输出时,尽量不要使用double。
1.3 浮点型的输出精度
设置浮点型输出精度程序示例
#include <iostream> #include <iomanip> using namespace std; int main() { float a = 12.3456789012345; double b = 12.3456789012345; cout<<"a = "<<setprecision(15)<<a<<endl;//用于设置输出的精度函数setprecision(输出位数) cout<<"b = "<<setprecision(15)<<b<<endl;//用于设置输出的精度函数setprecision(输出位数) system("pause"); return 0; } =>warning C4305: “初始化”: 从“double”到“float”截断(指向这行代码:float a = 12.3456789012345;) a = 12.3456792831421 b = 12.3456789012345
注:由于float的精度为6~7位,因此这里只输出了7位有效数字,而从第7位往后则均不正确。而double的有效位数是15~16位,对于精度要求高的时候,尽量用double,以免出错。
1.4 浮点型数值的比较
- 计算机对浮点型数值的比较:如果是数学意义上相等,却处理成相等。这是不可能的,也是错误的,因为精度毕竟有限。
错误的例子:
float a = 12.3456789012345; double b = 12.3456789012345; if(a == b) { cout<<"yes"<<endl; } else { cout<<"no"<<endl; } =>no(当超过精度位数,那么答案必然,因为精度不同。)
正确的例子:
const double EPSINON = 0.00001; float a = 12.3456789012345; double b = 12.3456789012345; double c = abs(a-b); if(c < EPSINON) { cout<<"yes"<<endl; } else { cout<<"no"<<endl; } =>yes(通过限定误差值,abs()是求绝对值函数。)
注:浮点型的值的大小不能直接用“ == ”或“ != ”来进行比较,应该设法运用求绝对值函abs()函数结合“ >= ”或“ <= ”来比较两个浮点型的大小。
(1)可以设定一个可接受的误差值,当误差小到一定程度的时候,就可以忽略了。譬如,abs(num1-num2)<0.00001。
(2)可以给高精度类型强制降精度,比如用这种方式:num1==static_cast(num2)。但注意,不要给低精度类型强制提升精度,如果这样就等于和编译器做的一样了,结果也是一样的。
1.5 十进制浮点数转换成二进制浮点数
- 在计算机内部,浮点数都是以二进制表示的,所以,对于十进制浮点数,要先转换成二进制浮点数。以手工方式来操作的方式分两步:
(1)整数部分的转换:采用”除2取余法“;
(2)小数部分的转换:采用”乘2取整法“;
————————————————————————————————
0.8125 = 0.1101(2)
————————————————
0.8125 * 2 = 1.625 0.1
0.6250 * 2 = 1.250 0.11
0.2500 * 2 = 0.500 0.110
0.5000 * 2 = 1.000 0.1101
————————————————————————————————
注:有时候,在转换中,二进制小数的某些位会周而复始地重复,以致无穷。由于计算机的表示是有限的,所以在计算机内只能截取到某个精度,而在文字上描述时,对重复的部分,其两端的数字各用一个着重号表示该段数字的重复。
1.6 二进制浮点数的位数及规格化
二进制浮点数规格化是通过调整浮点数的阶码使得该数的有效值在1与2之间,即二进制浮点数的整数部分为1。
查看三种精度浮点数的二进制位码 #include <iostream> using namespace std; int main() { float f1 = 19.2F; float f2 = 0.192e+02;//将double数转换为float,"+02"<=>10^2 int *pf = (int*)&f1; cout<<"单精度:"; for(int i=31; i>=0; i--) { cout<<(*pf>>i & 1)<<(i==31 || i==23 ? "-":""); } cout<<endl; double d1 = 19.2; double d2 = 0.192e+02F;//将float数转换为double int *pd = (int*)&d1; cout<<"双精度"; for(int i=63; i>=0; i--) { cout<<(*pd>>i & 1)<<(i==63 || i==52 ? "-":""); } cout<<endl; long double ld1 = 19.2L; double ld2 = 0.192e+02;//将doulble数转换为long double int *pld = (int*)&ld1; cout<<"长双精度"; for(int i=79; i>=0; i--) { cout<<(*pld>>i & 1)<<(i==79 || i==65 ? "-":""); } cout<<endl; system("pause"); return 0; } => 单精度:0-10000011-00110011001100110011010 双精度0-01100110011-0011001100110011001100110011001100110011001100110011 长双精度0-01100110011001-1001100110011001100110011001100110011001100110011001100 1100110011
参考文献 :
[1]《C++全方位学习》范磊——第四章
[2]《C++程序设计教程(第二版)》钱能——第三章
[3] 百度搜索关键字:C++数据类型、浮点型