打印双变量内容

时间:2010-03-24 10:02:52

标签: c printing double

我尝试了以下代码片段,输出令我感到惊讶:

#include <stdio.h>
#include <math.h>

int main()
{
            double num;
            unsigned char ch;

            ch = 19;
            num = 1.0E+20 ;
            num += ch * 1.0E+18;
            printf("E18 = %lf \n",num);
            printf("E18 = %e \n",num);

            num = 11.0E+21 ;
            num += ch * 1.0E+19;
            printf("E19 = %lf <------\n",num);
            printf("E19 = %e <------\n",num);

            num = 11.0E+22 ;
            num += ch * 1.0E+20;
            printf("E20 = %lf\n",num);
            printf("E20 = %e\n",num);

            num = 11.0E+23 ;
            num += ch * 1.0E+21;
            printf("E21 = %lf\n",num);
            printf("E21 = %e\n",num);

            num = 11.0E+24 ;
            num += ch * 1.0E+22;
            printf("E22 = %lf <------\n",num);
            printf("E22 = %e <------\n",num);
    return 0;
}

该计划的输出:

E18 = 119000000000000000000.000000 
E18 = 1.190000e+20 
E19 = 11190000000000000524288.000000 <------
E19 = 1.119000e+22 <------
E20 = 111900000000000001048576.000000
E20 = 1.119000e+23
E21 = 1119000000000000044040192.000000
E21 = 1.119000e+24
E22 = 11189999999999999366660096.000000 <------
E22 = 1.119000e+25 <------

为什么数据在以指数形式打印时损坏

5 个答案:

答案 0 :(得分:6)

因为,当数字变得足够大时,你会失去精确度:http://en.wikipedia.org/wiki/Floating_point

答案 1 :(得分:3)

数据未损坏;这就是浮点值在当今计算机中的作用。将浮点数视为固定的位数(尾数)和另一个指示小数点应放置位置的数字(指数)。对于更长,更准确的故事,Wikipedia is a good start

由于尾​​数的位数是固定的,因此它不能代表你在这里要求的极小部分。此外,因为它全部是二进制的,所以不能总是精确地表示十进制数字。

指数表示法只是将已知数字不准确的最后几位数字四舍五入,因此得出结果。

答案 2 :(得分:0)

双/浮点数随着它们变大而失去精确度 - 除了Tuomas发布的the Wikipedia article之外,这是另一个好的:

http://www.yoda.arachsys.com/csharp/floatingpoint.html

它的目标是.NET,但原则仍然适用。

答案 3 :(得分:0)

浮点数据类型使用有限数量的位来表示特定范围的数字。但是,在任何两个实数m和n之间可以存在无限数量的值。所以,你牺牲了精确度。

它以指数形式显示,因为并非所有数字都被打印出来。

作为测试,尝试使用大约10位小数打印值0.2,您将看到存储的值更像是0.1999999 ....

答案 4 :(得分:0)

您正在看到浮点固有的不精确性。

某些printf次转化可确保生成足够的有效数字,以唯一标识要打印的数字。这意味着如果有任何不精确,你会看到它。相反,默认的%e / %f表示通过舍入来隐藏不精确。

据我所知,%a(十六进制浮点)是实现此目的的唯一方法。根据{{​​3}},%lf被定义为与%f做同样的事情,即

  

l(ell)...对后续的a,A,e,E,f,F,g或G转换说明符没有影响。

所以这在技术上是标准库中的一个错误。