【问题标题】:How do I print in double precision?如何以双精度打印?
【发布时间】:2020-09-10 18:37:15
【问题描述】:

我对 C 完全陌生,我正在尝试完成一项作业。练习是打印 tan(x),其中 x 从 0 递增到 pi/2。

我们需要以 float 和 double 的形式打印它。我写了一个似乎可以工作的程序,但我只打印了浮点数,而我预计是双倍的。

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

int main()
{
    double x;
    
    double pi;
    pi = M_PI;
     
    for (x = 0; x<=pi/2; x+= pi/20)
    {
        printf("x = %lf, tan = %lf\n",x, tan(x));
        
    }
    
    exit(0);
}

我的问题是:

  • 为什么我得到浮点数,而我将变量定义为 double 并在 printf 函数中使用 %lf?

  • 我需要改变什么才能获得双打作为输出?

【问题讨论】:

  • 您没有使用floatprintf() 格式%lf 用于long double。格式 %f 用于 double,当传递给 printf() 时,float 值将提升为 doublefloat 没有格式(与 scanf() 不同)。如果您想要更多小数位,您可以使用例如%.12f
  • 你得到的输出怎么样让你觉得双打没有被打印出来?
  • 我使用了一个在线 C 编译器,我得到的输出有 6 个小数位。我知道双精度有 15 个十进制数字,所以因为我没有看到那么多十进制数字,所以我认为它是一个浮点数。 (geeksforgeeks.org/difference-float-double-c-cpp) 因此,根据我在这里得到的反馈,我现在知道我的输出是双倍的,我可以决定输出的位数。但是如何操作代码以使我的输出采用浮点表示法?
  • 没有“浮点表示法”这样的东西。 floatdouble 确实有不同的精度,但这并不能映射到确切的十进制位数。如果你想打印一个多或少的数字,或者固定的数字,或者科学计数法,或者其他修改,你可以改变格式说明符;有关详细信息,请参阅printf 的文档。

标签: c floating-point double


【解决方案1】:

"...但我只打印了floats,而我期望的是double"

您实际上是在输出double 值。

variadic 函数(包括printf())的float 参数通常被隐式提升为doublereference.

所以即使你的陈述

printf("x = %lf, tan = %lf\n",x, tan(x));

改为:

    printf("x = %f, tan = %f\n",x, tan(x));

它仍然会输出double,因为"%f""%lf" 都用作printf()(和其他可变参数函数)的double 格式说明符。

编辑以解决 cmets 中的以下语句/问题:

“我知道双符号有 15 位 [精度]。”

是的。但是,float/double 数据类型的实际 IEEE 754 指定特征与使用 printf() 函数中的格式说明符使它们出现的方式有所不同。

简单来说:

  • double 的精度是 float两倍 (2x)。

  • float 是一个 32 位 IEEE 754 单精度浮点数,符号 1 位,指数 8 位,值 24*,结果为 7 十进制位精度。

  • double 是一个 64 位 IEEE 754 双精度浮点数,其中 1 位用于符号,11 位用于指数,53* 位用于产生 15 十进制位精度。

* - 包括隐式位(对于正常数,它始终等于 1,对于次正常数,始终等于 0。此隐式位不存储在内存中),但不包括符号位。

"...但是使用 %.20f 我可以打印更多数字,这怎么可能?这些数字是从哪里来的?"

额外的数字是由模拟数字的二进制表示引起的不准确,再加上使用宽度说明符来强制显示比存储值实际表示的信息更多的信息。

虽然宽度说明符有其应有的地位,但它们也可能导致提供误导性结果。

【讨论】:

  • 感谢您的反馈!如果我的输出已经是双倍的,我如何才能得到它的浮点数,因为 printf 函数将变量提升为双倍?我知道双符号有 15 位数字。但是使用 %.20f 我可以打印更多的数字,这怎么可能?这些数字是从哪里来的?
  • @Terr070 - 请参阅编辑以了解在答案底部处理您的评论的详细信息。 (如果这已经解决了您的问题,请考虑通过单击答案顶部的空心复选标记来接受。)
【解决方案2】:

为什么我得到浮点数,而我将变量定义为 double 并在 printf 函数中使用 %lf

代码没有得到“浮动”,输出只是文本。即使编码的参数是 floatdouble,输出也是浮点数的文本翻译 - 通常是四舍五入。

printf() 只是遵循"%lf" 的行为:打印小数点后 6 位的浮点值。使用printf()"%lf" 的性能与"%f" 完全相同。

printf("%lf\n%lf\n%f\n%f\n", 123.45, 123.45f, 123.45, 123.45f);
// 123.450000
// 123.449997
// 123.450000
// 123.449997

我需要改变什么才能获得双打作为输出?

没什么,输出是文本,不是double。要查看更多数字,请以更高的精度打印。

printf("%.50f\n%.25f\n", 123.45, 123.45f);
// 123.45000000000000284217094304040074348449710000000000
// 123.4499969482421875000000000

如何操作代码以使我的输出采用浮点表示法?

尝试使用"%e""%a" 进行指数表示法。要更好地了解要打印多少位数:Printf width specifier to maintain precision of floating-point value

printf("%.50e\n%.25e\n", 123.45, 123.45f);
printf("%a\n%a\n", 123.45, 123.45f);

// 1.23450000000000002842170943040400743484497100000000e+02
// 1.2344999694824218750000000e+02
// 0x1.edccccccccccdp+6
// 0x1.edccccp+6

printf("%.*e\n%.*e\n", DBL_DECIMAL_DIG-1, 123.45, FLT_DECIMAL_DIG-1,123.45f);
// 1.2345000000000000e+02
// 1.23449997e+02

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-07
    • 2016-04-30
    • 2011-02-14
    相关资源
    最近更新 更多