yunfan188 2022-07-06 02:24 采纳率: 100%
浏览 102
已结题

【C语言】定义一个宏命令,实现对一个数值保留小数点后一位有效数字的问题疑问?

问题遇到的现象和发生背景

我写了一个保留小数点后一位有效数字的宏定义,不进行四舍五入处理,如下所示:

#define PRECISION_1(x) (((double)((int32_t)((x) * 10))) / 10)
问题相关代码,请勿粘贴截图

测试用例如下所示:

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

#define PRECISION_1(x) (((double)((int32_t)((x) * 10))) / 10)

int main()
{
    printf("result=%lf\n", PRECISION_1(3.1415926));
    double temp = 0.100000;
    printf("temp=%lf, result=%lf\n", temp, PRECISION_1(temp)); // --1
    printf("result=%lf\n", PRECISION_1(0.100000));
    printf("result=%lf\n", PRECISION_1(1677721.400000-1677721.300000)); // --2
    double x = 1677721.4-1677721.3;
    // float x = 1677721.4-1677721.3;  //改成float类型,结果又是正确的,离谱啊!
    printf("x=%lf, result=%lf\n", x, PRECISION_1(x)); // --3
    return 0;
}
运行结果及报错内容

使用 GCC 编译器进行编译:gcc test.c -o test (可以加 -std=c99 或 -std=c11)
运行结果如下:./test

result=3.100000
temp=0.100000, result=0.100000
result=0.100000
result=0.000000
x=0.100000, result=0.000000

可以看到上述代码第1处、第2处和第3处的 result 输出结果是有区别的,让人匪夷所思!

我的解答思路和尝试过的方法

我对 test.c 源码进行预处理后:gcc -E test.c -o test.i,打开 test.i 文件,关键代码如下:

......
typedef int int32_t;
......
# 7 "test3.c"
int main()
{
    printf("result=%lf\n", (((double)((int32_t)((3.1415926) * 10))) / 10));
    double temp = 0.100000;
    printf("temp=%lf, result=%lf\n", temp, (((double)((int32_t)((temp) * 10))) / 10));
    printf("result=%lf\n", (((double)((int32_t)((0.100000) * 10))) / 10));
    printf("result=%lf\n", (((double)((int32_t)((1677721.400000-1677721.300000) * 10))) / 10));
    double x = 1677721.4-1677721.3;
    printf("x=%lf, result=%lf\n", x, (((double)((int32_t)((x) * 10))) / 10));
    return 0;
}
我想要达到的结果

我这里不明白的是,为什么上述代码第1处、第2处和第3处的运行结果一个是0.100000,而另外两个却是0.000000,这让我感到很奇怪!
变量temp和x的值都是0.100000,PRECISION_1(temp)的结果是0.100000,而PRECISION_1(x)的值却是0.000000,离大谱啊!

还请C/C++语言开发们帮忙解答一下呀,感谢了!

  • 写回答

2条回答 默认 最新

  • 私房菜 移动开发领域优质创作者 2022-07-06 11:19
    关注

    这个问题还是提的挺好的,主要就是需要考虑float 和doubule 在内存中的分布情况。这个你可以网上搜一下。
    就这个代码,我们先直接来看第 3 处,我给你看下x 在内存中的分布:
    (gdb) p x
    $3 = 0.099999999860301614
    (gdb) p &x
    $4 = (double *) 0x7fffffffe210
    (gdb) x /16g 0x7fffffffe210
    0x7fffffffe210: 0x3fb9999999000000 0x4139999966666666

    看到了没0x7fffffffe210 为x 的内存地址,占用8个字节的话,值在内存中为 0x3fb9999999000000,转换成十进制为 0.099999999860301614 ,所以,用你的宏定义,那肯定是0.000000

    再来看下第 2 处,虽然是宏定义,但是在内存中这两个数是存放在静态区的,所以,结果跟第 3 处基本是一样的。

    至于第 1 处,本身在内存中的数就是0.1,所以,打印出来也是0.100000

    希望对你有帮助,有其他问题,也可以随时问我。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 7月19日
  • 已采纳回答 7月11日
  • 创建了问题 7月6日

悬赏问题

  • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
  • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
  • ¥15 手机接入宽带网线,如何释放宽带全部速度
  • ¥30 关于#r语言#的问题:如何对R语言中mfgarch包中构建的garch-midas模型进行样本内长期波动率预测和样本外长期波动率预测
  • ¥15 ETLCloud 处理json多层级问题
  • ¥15 matlab中使用gurobi时报错
  • ¥15 这个主板怎么能扩出一两个sata口
  • ¥15 不是,这到底错哪儿了😭
  • ¥15 2020长安杯与连接网探
  • ¥15 关于#matlab#的问题:在模糊控制器中选出线路信息,在simulink中根据线路信息生成速度时间目标曲线(初速度为20m/s,15秒后减为0的速度时间图像)我想问线路信息是什么