代码之家  ›  专栏  ›  技术社区  ›  qwerty000

不精确性

  •  1
  • qwerty000  · 技术社区  · 7 年前

    我正在尝试打印m_pi,但我认为我没有使用正确的格式说明符。输出应该是:3.14159265358979323846,但我得到3.14159265358979300000。

    int main(void)
    {
        printf("%.20f\n", M_PI);
        return 0;
    }
    

    我试过使用%lf,%lg,%e,%g,但都不起作用,所以我不确定这个错误是来自格式说明符,还是与我使用的硬件有关。

    3 回复  |  直到 7 年前
        1
  •  4
  •   Pascal Cuoq    7 年前

    假设编译器映射 double 浮点类型到IEEE754双精度,然后 双重的 有53位二进制精度。浮点数以2为底表示的事实意味着它不是可以表示为 双重的 它有一个简短的十进制表示。尤其是 双重的 最接近_的是一种紧凑的表示法,只有53个二进制精度,但以十进制表示为3.141592653589793115997963468544185161590576171875。这不是_到50位十进制数字的近似值!它是的近似值,有53个二进制数字的精度,这意味着大约17个第一个十进制数字是正确的,而其他数字只是因为基数2之间的不匹配而存在。 M_PI 以10为基础,我们现在正在讨论它的价值。

    这意味着你可以期待 质量 printf 要打印的实现 3.14159265358979311600 . 请注意,这不是您在问题中所说的字符串,而是后面20位的四舍五入十进制表示。 . 的实际值 MYPI . 不管怎样,你可以期待 质量 普林特 实现打印显示 双重的 尽管在最坏的情况下 there can be 750 or so .

    C标准 does not force 全部的 普林特 要具有此属性的实现:

    对于E、E、F、F、G和G转换,如果 小数位数最多为小数位数,则结果应为 正确的圆形。如果有效小数位数为 大于小数点挖掘,但源值完全可表示 如果使用十进制数字,那么结果应该是精确的 带尾随零的表示。否则,源值为 以两个相邻的十进制字符串L<U为界,两者都有十进制数字 有效数字;结果十进制字符串d的值应 满足L<=D<=U,额外规定错误应 对当前的舍入方向有正确的符号。

    更容易实现最多打印 双重的 的精确值,然后为零,C标准允许这样的实现。这可能就是编译器发生的事情。 (采用此快捷方式的编译器通常也不会实现__current rounding direction_157;约束。)

        2
  •  1
  •   kshetline    7 年前

    双精度浮点数的精度只有这么高。它少于20位,所以在某个时刻,无论你要求多少位的精度,你要么得到无意义的噪音,要么得到全部零。

        3
  •  0
  •   Luis Colorado    7 年前

    double ,在大多数遵循IEEE-754的体系结构中实现的只有64位,一位表示符号,11表示指数,剩下52位表示尾数(53,因为第一个有效位总是 1 ,由于这个原因,格式中没有包含,所以在基数2中有53个有效数字),这意味着大致( (52+1)/ln(10)*ln(2) ~= 15.95 以10为基数的有效数字)的近似值 M_PI 对于这个精度应该是类似的。

    3.141592653589793
    

    这是π的精确数字的最大值。有一个近似的差别 2 * 10^(-16) 在你得到的值和π的实际值之间,可能是由于算法 printf 用于获取该数字的十进制版本。

    但是您不能期望从IEEE-754实现中得到更精确的结果,因此您得到的答案会受到您要求的位数的影响。

    顺便问一下,你试过用吗 "%.200f" 设置字符串格式?至少,在gcc中,您可以得到很多非零位数字,以完成您所请求的全部精度(在基2中,从最后一位开始算起,您就得到了所有零位数字)。在MSVC中,我知道它有时会被零填充(使用某种算法),这就是发生在您身上的事情。但是,请始终指出,在64位浮点数字的IEEE-754实现中,结果最多有16个有效/精确数字(好吧,小于16,因为结果接近它,但在下面)。

    推荐文章