zoukankan      html  css  js  c++  java
  • 数字数据类型及其对应转移字符

    说明: 

    格式字符:c   输出一个字符。

         s   输出一个字符串。

         e   以指数形式输出实型数。

         f     以小数形式输出实型数。

         g   自动决定输出格式为e和f中较短的一种,不打印无效的零。

         %   输出%。

     

    注意:对于单精度数,使用 %f 格式符输出时,仅前7位是有效数字,小数6位。

       对于双精度数,使用 %lf 格式符输出时,前16位是有效数字,小数6位。

     

    长度修正符

      l:对整型指定长整型long

          例:%ld , %lx , %lo , %lu

        对实型指定双精度double

               例:%lf

        h:只用于整型的格式字符修正为short

               例:%hd , %hx , %ho , %hu

    格式输出字符:printf

    使用:向终端输出若干个类型任意的数据。

    形式:printf (格式控制符,输出列表)

    说明:

    格式控制符:%  格式说明引导符。

          -  指定左对齐输出。

          0  指定空位填零。

          m.n 指定输出域宽度及精度。

          l.h 输出长度的修正。

         格式字符   指定输出的数据类型。

    说明:

    格式字符:指定输出项的数据类型和输出格式。

         d  有符号十进制整数。

         o  无符号八进制数。

         x  无符号十六进制数。(小写的x格式中用小写字母a,b,c,d,e,f来表示10到15之间的数,大写的X则用大写的ABCDEF来表示10到15之间的数)

         u  不带符号的十进制整数。

     

    http://blog.csdn.net/yahohi/article/details/7701434

     

    1. printf("%f ",5);  
    2. printf("%d ",5.01);   
    3. printf("%f ", (float)5);    
    4. printf("%f ", 5.f);    


    输出结果:

    看到结果,会感觉非常奇怪。1处怎么会输出0呢?2又为何会显示这么大的一个数呢?

    解释:

    下面是转自网上的一篇博客的解释

    1,之所以没输出5,这是C语言设计的原因。
    2,之所以输出0,这是计算机体系结构的问题。

    具体来说:

    printf函数不会进行任何类型转换,它只是从内存中读出你所提供的元素的值(按照%d,%f等控制字符提示的格式)。C语言设计中,int类型一般是32bit或者16bit,而float一般是64bit,并且有可能使用科学计数保存。这点就和huhugo88所说一样,5在内存中为00000000,00000101。而且5一般都在静态区,程序的静态存储区默认是0,那么当用%f来读时,就会读64bit,也就是会读之前的很多位0,最后按照(有效数字)×(基数2)pow(指数)的方式来取数,自然结果是0

    之所以Vc中不允许这种情况,而有些编译器就允许这么输出就是编译器设置的问题。按理说,这样访问内存是属于越界访问,应该禁止。不过只是读,伤害性不大而已。  对于单精度浮点数(32bit),不少c语言编译系统以24位表示小数部分(包括1bit符号位),以8位表示指数部分。 ==========================printf("%d ",5.01);  为什么输出一个大数?在讲这个题目之前,预备知识,讲一下,printf函数,输入参数是读入缓冲区保存,再按照%?的格式从缓冲区中读出数据,并据此格式解释数据。

    有了这个知识之后,在讲程序员面试宝典上看到一个题:

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
        printf("%d ",5.01);   
    return 0;   
    }   
    输出结果为:188978561  
    然后开始研究为什么会是这个数?

    5.01是double类型,内存中占8个字节,保存在缓冲区。而%d为整型,占4个字节,printf从缓冲区中读入4字节,先读到低32位的数据。也就是说printf输出的应该是5.01以double类型保存数剧的低32位。为了检验此结果是否正确,对比5.01在内存中的表示与输出。

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
    double d = 5.01;   
    int *p = (int *)(&d);   
    int rst = 1889785610;   
        printf("1).%x ",*p);   
        printf("2).%x ",*(p+1));   
        printf("3).%x ",rst);   
    return 0;   
    }   
    输出为:   
    1).0x70a3d70a   
    2).0x40140a3d   
    3).0x70a3d70a  
    这也就证明了%d输出了5.01的低32低。5.01的double类型,在内存的的表示为0x40140a3d70a3d70a。

    事情看似也就完成了。

    我又想,如果输入是浮点类型的5.01f,又会发生什么呢?

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
    float f = 5.01f;     
    int *p = (int *)(&f);        
        printf("1).0x%x ",*p);     
        printf("2).0x%x ",5.01f);     
    return 0;     
    }   
    输出:   
    1).0x40a051ec   
    2).0x80000000  
    我们发现,此时输出的并不是浮点类型5.01f的内存的表示,这是为什么呢?

    然后看到一个说法,是printf会把%f按double类型输出,也就是说会把参数float型的转成double型在输出。

    但现在并不是%f,当然用%f显示的是正确的结果。于是我猜测,printf是将所在float型读入的数据都自动的转化为double型了,然后%f就按double处理,而我们这是%d,所以显示的为float转化为double型后的低4字节。

    验证此想法:

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
    double f = 5.01;     
    int *p = (int *)(&f);   
        printf("1).0x%x ",*p);   
        printf("2).0x%x ",*(p+1));     
        printf("3).0x%x ",5.01f);     
    return 0;     
    }   
    输出:   
    1).0x70a3d70a   
    2).0x40140a3d   
    3).0x80000000  
    但是我们发现结果并不一样,于是我又猜想,也是许printf将float转化为double的方式与默认的方式不一样

    5.01d的默认的表示为:0x40140a3d70a3d70a,在上面已经说明了

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
        printf("0x%8x 0x%8x ",5.01f);   
    return 0;   
    }   
    输出为:   
    0x80000000   
    0x40140a3d  
    与是发现printf将5.01f->5.01d的表示是:0x40140a3d80000000

    接着就是看这两个值是否都是为5.01了:

    view plaincopy to clipboardprint?

    #include "stdio.h" 
    int main(int argc, char* argv[])   
    {   
    int d1[2], d2[2];   
        d1[0]=0x80000000;   
        d1[1]=0x40140a3d;   
        d2[0]=0x70a3d70a;   
        d2[1]=0x40140a3d;   
    double *p1 = (double *)d1;   
    double *p2 = (double *)d2;   
        printf("1).%f ",*p1);   
        printf("2).%f ",*p2);   
    return 0;     
    }   
    输出为:   
    1).5.010000   
    2).5.010000  
    也就证明了0x40140a3d80000000,与0x40140a3d70a3d70a都是5.01d在机器中的表示。前者为5.01f(0x40a051ec)由printf转化为double后的表示,后者为5.01d的默认的表示。

    总结:printf将输的浮点型参数全都自动转化为双精度型,且与默认的双精度的表示方法是不同的。最重要一点,printf不安全,类型不安全,要是类型不对了,也许我们就挂了^_^


    printf("%d",5.01)和printf("%f",5)的输出结果

    通过以上解释,我们大致明白:

    1. printf输出float型时,会自动转化成double型;

    2. 由于存储时,都是先低位,再高位,同时经过转化成double,前面会取很多0(越界访问);

    3. 5.01,打印时按照int来取,只取前四个字节。

  • 相关阅读:
    HUST 1372 marshmallow
    HUST 1371 Emergency relief
    CodeForces 629D Babaei and Birthday Cake
    CodeForces 629C Famil Door and Brackets
    ZOJ 3872 Beauty of Array
    ZOJ 3870 Team Formation
    HDU 5631 Rikka with Graph
    HDU 5630 Rikka with Chess
    CodeForces 626D Jerry's Protest
    【POJ 1964】 City Game
  • 原文地址:https://www.cnblogs.com/chengxuyuandashu/p/3562283.html
Copyright © 2011-2022 走看看