c语言的printf输出浮点数的一些问题


在printf时:如果以%f格式输出,将输出8个字节(scanf输入时,%f是4个字节)

                   在参数入栈时如果是float型或者double型 直接入栈8个字节,此时输出及后续输出都没问题

                    但如果参数小于8个字节且不是float型:比如int   shor int  ,就会扩展符号位,成为4个字节再入栈,但是输出的是8个字节,所以会读取其他参数的入栈结果

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[])
{
    int a = 3;
    int b = 5;
    printf("%f %d\n", a, b);
    return 0;
}

在linux下的gcc输出结果是:  0.000000    134513801      -->后面这个值是一个无用值,比如int x;  printf("%d\n", x)  -->输出的就是:134513801

在vs2013下的输出结果是:0.000000   0     vs中对int x; printf("%d\n",x)会出现错误,因为x未初始化,

-->上述入栈结果是(十六进制):

栈顶                                 栈底

     03 00 00 00    05 00 00 00  

-->%f 读取8个字节,直接把b的入栈结果读走了


  符号位  阶码  尾数  总位数
  短浮点数   1    8   23   32
  长浮点数   1    11   52   64

在32位浮点数的读取中:从内存中读出0x 03 00 00 00后,因为是小端模式,所以变成0x 00 00 00 03

 0   000 0000 0  000 0000 0000 0000 0000 0011

第一个0是符号位:表正

第2到9位是阶码,32位浮点数的指数偏移量是127, 所以此处是-127

后面的均为小数点后面的:小数点前为1

-->(1 + 2^(-22) + 2^(-23)) * 2^(-127)

趋近于0;

在64位浮点数中:则阶码偏移量为:2^(10) - 1


例1:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[])
{
    int a = 3;
    int b = 0xffffffff;
    printf("%f %d\n", a, b);
    return 0;
}

在gcc中结果为:-nan    134513801     -->-nan表示负无穷大

在VS2013中结果为:-1.#QNAN0   0

printf的栈中: 03 00 00 00 ff ff ff ff

-->按%f读取的时候:ff ff ff ff 00 00 00 03

-->按浮点数解析相应的位!


例2:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, const char *argv[])
{
    int a = 0x10000003;
    int b = 0x40110000;
    printf("%f %d\n", a, b);
   
    int c[2];
    c[0] = 0x10000003;
    c[1] = 0x40110000;
     double d = *(double*)c;
     printf("%f\n", d);
    return 0;
}

gcc中:


分析:

在第一个printf的栈中:  03 00 00 10 00 00 11 40

-->以%f读出时出栈结果:0x 40 11 00 00 10 00 00 03

-->64位浮点数解析:0100 0000 0001 0001 0000 0000 0000 0000 0001 0000 0000 0000 0000 0000 0000 0011

符号位:0

阶码:100 0000 0001    -->11位  -->减去偏移量:2^(10) -1  -->结果为2

小数位:0001 0000 0000 0000 0000 00....

最后大小:(1 + 2^(-4) + 2^(-52) + 2^(-51) + 2^(-24)) * 2^(2)

 -->2进制:100 + 2^(-2)   -->4.250000 


例3:
反过来看
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char *argv[])
{
    int a = 5;
    float b = 3.0;
    printf("%d %d\n" , a, b);
    return 0;
}

输出结果: 5   0

b虽然是4个字节的float型,但是在入栈时会变换为8个字节的fdouble型
--->float型的3.0的表示:0x 40 40 00 00
                       -->内存中: 00 00 40 40
                      -->printf输出时入栈变为扩展8个字节的double型: 00 00 00 00 00 00 08 40
-->此时printf的栈中:
                        05 00 00 00  00 00 00 00 00 00 08 40
-->以%d格式输出两次: 5   0
32位的float型的3二进制码:   0 100 0000 0 100  0000 0000 0000 0000 0000
64位的double型3的二进制:   0 100 0000 0000  1000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
对比:                   32                    64
符号位                    0                     0
阶码:                100 0000 0       100 0000 0000    -->64位在32位后面添加了3个0
尾数 :               100.....               100....                   -->64位在32位后面添加了29个0

总结:
 printf 以%f格式输出时输出8个字节,float类型输出时入printf的栈要扩展为double型的8个字节!
printf的返回值为实际控制输出的字符数(不包括字符串末尾的'\0'),

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]中提到了C语言中使用printf输出浮点数问题。在C语言中,可以使用格式化字符串"%f"来输出浮点数。然而,由于计算机的浮点数表示存在精度问题,所以输出的结果可能不够精确。为了增加输出的精度,可以使用指定精度的格式化字符串,例如"%.8f"表示输出浮点数并保留8位小数。这样可以提高输出的精度。\[1\] 另外,引用\[3\]中提到了printf在传递参数时,若实参为float型数据,编译时会自动转换为double类型。因此,在使用printf输出浮点数时,可以将float型数据转换为double型数据,以提高输出的精度。例如,可以使用"(double)10.9f"来将float型数据转换为double型数据并输出。\[3\] 综上所述,使用printf输出浮点数时,可以使用格式化字符串"%f"并指定精度,同时将float型数据转换为double型数据以提高输出的精度。 #### 引用[.reference_title] - *1* [C语言printf输出浮点数的精度问题](https://blog.csdn.net/u011426016/article/details/119868622)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [printf输出浮点数遇到的问题 %f的问题](https://blog.csdn.net/lileiyuan1985/article/details/130862201)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [printf 输出浮点数](https://blog.csdn.net/weixin_30732825/article/details/94995182)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值