【问题标题】:Printing double variable contents打印双变量内容
【发布时间】:2010-03-24 10:02:51
【问题描述】:

我尝试了以下代码 sn-p 并且输出让我感到惊讶:

#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 <------

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

【问题讨论】:

    标签: c printing double


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      数据没有损坏;这就是浮点值在当今计算机中的工作方式。将浮点数视为 固定 位数(尾数)和另一个指示小数点应放在何处的数字(指数)。如需更详细、更准确的故事,请Wikipedia is a good start

      由于尾​​数的位数是固定的,它不能代表您在这里要求的微小部分。此外,由于都是二进制,十进制数不能总是精确表示。

      指数符号只是将已知数字不准确的最后几位四舍五入,从而得出您的结果。

      【讨论】:

        【解决方案3】:

        双/浮点数随着变大而失去精度 - 除了the Wikipedia article Tuomas 发布的内容之外,这里还有一个不错的:

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

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

        【讨论】:

          【解决方案4】:

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

          指数形式看起来不错,因为并非所有数字都被打印出来。

          作为测试,尝试将值 0.2 打印到小数点后 10 位左右,您会发现存储的值更像 0.1999999....

          【讨论】:

            【解决方案5】:

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

            保证某些printf 转换会产生足够的有效数字来唯一标识正在打印的数字。这意味着如果有任何不精确,你会看到它。相反,默认的%e/%f 表示通过四舍五入隐藏了不精确性。

            据我所知,%a(十六进制浮点)是实现这一目标的唯一方法。根据the POSIX spec%lf被定义为和%f做同样的事情,即

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

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

            【讨论】:

              猜你喜欢
              • 2018-08-15
              • 2014-08-06
              • 2018-08-09
              • 1970-01-01
              • 2011-01-23
              • 1970-01-01
              • 1970-01-01
              • 2023-02-03
              • 2018-05-11
              相关资源
              最近更新 更多