本文主要是介绍c++单精度和双精度的运算例子(计算机占位存储),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
计算机中float, double类型数据分别占据4,8个字节,其中float类型和double可以表示的小数位数不同,导致了精度不同。double的精度更高。
计算机中数据的表示由:符号位, 指数位,尾数位组成。比如一个float类型数字的二进制由左到右依次是符号位,指数位,尾数位。
类型 | 符号位 | 指数位 | 尾数位 | 总位数(bit) |
float | 1 | 8 | 23 | 32 |
double | 1 | 11 | 52 | 64 |
数字1.4在计算机中的存储转换如下:
先将整数和小数都变二进制表示:1.0110 0110 0110 0110 0110 011,然后整数部分不需要右移,所以float的指数位=2*7-1+0=127;double的指数位=2*10-1+0=1023。各个部分的二进制表示如下。
1.4的不同存储 | 符号位 | 指数位 | 尾数位 | 16进制表示 |
float | 0 | 01111111 | 0110 0110 0110 0110 0110 011 | 3FB33333 |
double | 0 | 01111111111 | 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 | 3FF6666666666666 |
在c++单精度和双精度的运算结合如下两个test示例理解如下:
#include <iostream>float f1 =1.4;
float f2 = 5.0;
float f3 = 7.0;
int i = 7;
using namespace std;void test1()
{printf("test %f %f %f\n", f1 * f2, f1 * 5.0, f3 / f1);cout << (f1 * f2 == i) << '\t' << (f1 * f2 == f3) << endl;cout << (f1 * 5.0f == f3) << '\t' << (f1 * f2 == f1 * 5.0f) << endl;cout << (f3 / f1 == 5.0) << '\t' << (f3 / f1 == f2);
}void test2()
{printf("test %f %f %f\n", f1 * f2, f1 * 5.0, f3 / f1);cout << (f1 * f2 == i) << '\t' << (f1 * f2 == f3) << endl;cout << (f1 * 5.0 == f3) << '\t' << (f1 * f2 == f1 * 5.0) << endl;cout << (f3 / f1 == 5.0) << '\t' << (f3 / f1 == f2);
}
int main(void)
{cout<<"test1"<<endl;test1();cout<<endl<<"test2"<<endl;test2();cout<<endl<<endl<<"验证输出"<<endl;double f11=1.4;cout<<"sizeof(5.0)="<<sizeof(5.0)<<", sizeof(f1*f2)=" <<sizeof(f1*f2)<<", sizeof(f3/f1)=" <<sizeof(f3/f1)<<endl;cout.precision(20);cout<<"1.4的单精度 f1="<<f1<<endl<<"1.4的双精度 f11="<<f11<<endl;cout<<"双精度转单精度 double2float: "<<float(f11)<<endl;cout<<"单精度转双精度 float2double: "<<double(f1)<<endl;cout<<"单精度*单精度 f1*5.0f="<<f1*5.0f<<", 单精度*双精度 f1*5.0="<<f1*5.0<<", 双精度*双精度 f11*5.0="<<f11*5.0<<endl;cout<<"当单精度*单精度结果有小数时候:"<<endl; cout<<"单精度*单精度 f1*6.0f="<<f1*6.0f<<", 单精度*双精度 f1*6.0="<<f1*6.0<<", 双精度*双精度 f11*6.0="<<f11*6.0<<endl;cout<<endl<<"i.和j. 的验证:"<<endl;cout<<"f3/f2==1.4 =>"<< (f3/f2==1.4)<<", f3/f2==f1 =>"<<(f3/f2==f1)<<endl;cout<<endl<<"d.的假设验证:"<<endl;cout<<"float(f1*5.0)==i =>"<<(float(f1*5.0)==i)<<endl;f1=0.125;cout<<"f1 * 56.0 == i =>"<< (f1 * 56.0 == i)<<endl;return 0;}
test1和test2的两段代码涉及的是float类型和double类型数据在计算机中的存储问题。
用到的基础知识:
1, C++中默认5.0是一个double类型,5.0f表示指定这是一个float类型的数字。
2, 精度(float*double)=> double*double=精度(double), 精度(float*float)=精度(float), 精度(double*double)=精度(double)
3, float类型用4个字节表示,double类型用8个字节表示,double可以用更多的位表示小数点部分(这部分知识可以参考数字在计算机中的表示,https://blog.csdn.net/ultrakang/article/details/39322275),所以有小数的情况下,double比float精度更高。而float转double精度不变,double转float精度降低。
4,float和double转换中精度降低的情况只作用在存在小数位情况。且只存在于小数位的非0尾数大于23bit情况下(因为float尾数是23个bit, double尾数是52个bit)。
再来看本例中给定的数据 f1=1.4; f2=5.0; f3=7.0; i=7。共进行了如下的运算结果比对,跟着对应的结果分析。
a. f1 * f2 == i =》1,左边 f1*f2 等效于 float*float,结果仍然是float,恰好是整数,所以f1 * f2 == i 成立。
b. f1 * f2 == f3 =》1,左边 同 a. ,右边f3是float类型,不涉及数据类型转换,精度不变,所以f1 * f2 == f3 成立。
c. f1 * 5.0f == i =》1,左边 f1*5.0f 等效于float*float,其它同a. ,所以f1 * 5.0f == i 成立 。
d. f1 * 5.0 == i =》0,左边 f1*5.0等效于double*double, f1=1.4,1.4作为float和double两种类型在计算机存储的精度是不同的,并且结果也是double类型,精度更高,所以f1 * 5.0 == i 不成立,如果将f1*5.0转换成float类型则成立,即:float(f1*5.0)==i 成立。或者将本例中f1=1.4换成f1=0.125(即一个小数点位数可在23bit之内表示的数 , 则f1 * 56.0 == i 成立,因为0.125值的float和double类型在计算机存储中是一样的。
e. f1 * f2 == f1 * 5.0f =》1,右边f1 * 5.0f是float*float,不涉及类型转换问题,同b. 所以f1 * f2 == f1 * 5.0f 成立。
f. f1 * f2 == f1 * 5.0 =》0,右边同d. 1.4在计算机中作为float和double表示的精度不同,f1*5.0是double*double=double,比f1*f2的float*float=float精度更高,所以f1 * f2 == f1 * 5.0不成立。
g. f3 / f1 == 5.0 =》1, 左边float/foat=float,结果用float类型表示,小数位尾数为0,右边double类型的5.0的小数位尾数也都是0,所以f3 / f1 == 5.0 成立。可以结合下面的 i. 来理解。
h. f3 / f1 == f2 =》1, 左边和右边都是float类型,精度不变,所以 f3 / f1 == f2成立。可以结合下面的j. 来理解。
补充:
i. f3 / f2 == 1.4 =》0, 左边结果float类型,右边1.4是double类型,精度不同,所以f3 / f2 == 1.4不成立。
j. f3 / f2 == f1 =》1,右边类型是float,1.4用float表示,不涉及精度降低问题,所以f3 / f2 == f1 成立。
cout默认打印出7位有效数字,所以第一行打印的结果都一样。
上面的验证结果如图:
这篇关于c++单精度和双精度的运算例子(计算机占位存储)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!