我写了一个保留小数点后一位有效数字的宏定义,不进行四舍五入处理,如下所示:
#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++语言开发们帮忙解答一下呀,感谢了!
这个问题还是提的挺好的,主要就是需要考虑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
希望对你有帮助,有其他问题,也可以随时问我。
最后那个输出小数位增大,就会发现,浮点数保存的是近似值。
printf("x=%.20lf, result=%.20lf\n", x, PRECISION_1(x));
输出
x=0.09999999986030161381, result=0.00000000000000000000