C语言里面关于double类型的打印:%lf , %le , %lE
e/E是指数形式的,不过e打印的是小写,E打印的是大写。
g/G会截断一些小数,比较不精确。
%e double Signed value having the form [ – ]d.dddd e [sign]ddd where d is a single decimal digit, dddd is one or more decimal digits, ddd is exactly three decimal digits, and sign is + or –.
%E double Identical to the e format except that E rather than e introduces the exponent.
%f double Signed value having the form [ – ]dddd.dddd, where dddd is one or more decimal digits. The number of digits before the decimal point depends on the magnitude of the number, and the number of digits after the decimal point depends on the requested precision.
%g double Signed value printed in f or e format, whichever is more compact for the given value and precision. The e format is used only when the exponent of the value is less than –4 or greater than or equal to the precision argument. Trailing zeros are truncated, and the decimal point appears only if one or more digits follow it.
%G double Identical to the g format, except that E, rather than e, introduces the exponent (where appropriate).
一、实型常量
实型也称为浮点型,实型常量也称为实数或浮点数。
1.在纯C中,实型常量只能用十进制表示,但是有两种形式。
(1)十进制小数形式:由数字0-9以及小数点构成,其中,小数点是必不可少的,如356.0、12.2等都是合法实数,65不是合法实数,因为缺少了小数点。
(2)指数形式:由十进制数加阶码标志“E/e”组成,一般形式为a E n,其中a为十进制整数,E为阶码标志,n为十进制整数作为阶码,如123E5表示123*10^5,使用指数形式时,要注意E之前必须有数字,之后的阶码必须为整数。和数学中的科学计数法不同,一个实数可以有多种指数形式,如123.789可以表示为1.23789E2或12.3789E1或0.123789E3这些都是合法的,但是只有第一种才是规范化的指数形式,程序唉输出结果时都是以该种形式输出,但是其他形式在使用是也没有任何错误。
2.在纯C中,也可以使用后缀“F/f”来声明一个数是浮点数,如365F和365.0是等价的。
3.实例程序
main()
{
printf("%f\n",365.0);
printf("%f\n",365);
printf("%f\n",365F);
}
运行结果是
365.000000
0.000000
365.000000
第二行输出错误的原因是,由于在使用时没有加入小数点,也没有使用后缀F将其声明为浮点数,所以365不是合法实数,不被编译器认可。
二、实型变量
1.实型数据在内存中的存放形式:实型数据在内存中被分为符号部分,小数部分和指数部分三部分存放,例如-1.23456在内存中被分为“-”、“.123456”、“1”三个部分,一个实型数据占用4个字节的内存空间(1byte=8bits)通常,一般的C语言编译器会占用24位存放小数,8位存放指数,事实上,电脑在存取小数部分时,是以二进制形式的,而指数部分则是以2的幂指数形式存放的。
2.实型数据的小数位数越多,代表有效数字越多,精度也就越高,而指数位数越多,器表示的数的范围就越大。
3.实型变量的分类:实型变量可以分为三类,
(1)单精度型:占用4字节内存空间,数值范围为3.4E-38到3.4E+38,有效数字为七位。
(2)双精度型:占用8字节内存空间,数值范围为1.7E-308到1.7E+308,有效数字为十六位。
(3)长双精度型:只是知道有这种数据类型,不过没有具体的数据,那位高人知道的话请补充一下。
4.实型变量的定义格式和规则与整型数据相同,所以每一个实型数据在使用前必须先定义。
实例:
float m,n; /*定义m,n为单精度实型变量*/
double a,b,c; /*定义a,b,c为双精度实型变量*/
实例2:
main()
{
float a;
double b;
a=5555.55555;
b=5555.5555555555;
printf("%f\n%f\n",a,b);
}
运行结果为5555.555664
5555.555556
分析:变量a被定义为float,变量b被定义为double,所以a的有效数字为七位,所以输出时5555.555之后的数字是无效的,而b的有效数字虽然为十六位,但是由于具体编译器的限制,只运算到小数点后六位,其余位数四舍五入。
P.s编程技巧:对于实型数据,由于精度差别,大小差异极大的数值直接进行运算可能会丢失一部分数据。
三、puzzle from:
float c = 12.5;printf("%d\n", c);printf("%d\n", *(int *)&c);
参考答案:该项程序输出如下所示,01095237632原因是:浮点数是4个字节,12.5f 转成二进制是:01000001010010000000000000000000,十六进制是:0×41480000,十进制是:1095237632。这是第二个输出的原因。对于第一个,为什么会输出0,我们需要了解一下float和double的内存布局,如下:float: 1位符号位(s)、8位指数(e),23位尾数(m,共32位)
double: 1位符号位(s)、11位指数(e),52位尾数(m,共64位)
然后,我们还需要了解一下printf由于类型不匹配,所以,会把float直接转成double,注意,12.5的float和double的内存二进制完全不一样。别忘了在x86芯片下使用是的反字节序,高位字节和低位字位要反过来。所以:float版:0×41480000 (在内存中是:00 00 48 41)
double版:0×4029000000000000 (在内存中是:00 00 00 00 00 00 29 40)
而我们的%d要求是一个4字节的int,对于double的内存布局,我们可以看到前四个字节是00,所以输出自然是0了。
这个示例向我们说明printf并不是类型安全的,这就是为什么C++要引如cout的原因了。