小数常量数据的一个有意思的问题

最近看网上帖子时,看到一位网友提到的一个有意思的问题:

int main()
{
float a;
a=1.1;
}
当我编译这样一段程序,VC会提示:warning C4305: '=' : truncation from 'const double ' to 'float '。
经过百度,原来“在C语言中,如果不指定数据类型,那么小数常量会被认为是 double 类型”。
a是float,而1.1是double。 double 不能隐式转换为 float ,所以才会产生这个warning。
可是!!当我将1.1改为1.5,再次编译,编译器却没有提示warning!(我又再次把1.5改为10.5,编译后仍然没提示warning)
我发现:凡是类似于X.5这种形式的常量都不会提示warning。

首先,需要说明的是,在C/C++中,以小数形式给出的数据常量,如果不加特别说明,都认为是double型数据

此处涉及到小数数据从十进制到2进制的一个转换。比如:

十进制的1.5,其在2进制中表示就是1.1,这个数值大小既可以在float的精度内准确表示也可以在double的精度内准确表示,因此,在语句:

float a = 1.5; 中,不会出现对数据的截断(truncated)。

而对于十进制的数值1.1,1.3,其表示成二进制小数时,位数是无限循环的。例如1.1的二进制表示应该为:1.000110001100011………….

对于语句:float a = 1.1;

编译器在执行该语句的时候,会首先将数值1.1转换成二进制下符合double精度的表示值(此处应该也可能会存在截断问题,因为1.1二进制表示是无线循环的),且此处1.1的二进制表示值应该会填满double型数据的所有位。故而在向低精度的float型数值做转换的时候会存在截断。

拓展:如果有如下的一条蛋疼的语句:

double testdouble= 1.11111111111111111111111113333333333333333333333;

cout<<testdouble<<endl;

输出时会发现testdouble=1.11111,而且这里编译器不会有warning。这里的解释应该是常量值1.11111111111111111111111113333333333333333333333在编译器将其视作const double型数据时,就已经产生了截断,因为计算机double型没有那么高的精度来保存这么多位数,故而最终只保存了1.11111这个值,但是编译器对于这种截断不会报错或者警告。

原文地址:https://www.cnblogs.com/jiayouwyhit/p/3248504.html