【发布时间】:2017-03-23 05:26:59
【问题描述】:
这是 ANSI C 代码:
float x = 3.14159264351134890172;
double y = 3.14159264351134890172;
long double z = 3.14159264351134890172;
printf("%f\n",x);
printf("%f\n",y);
printf("%f\n",z);
printf("%.20f\n",x);
printf("%.20f\n",y);
printf("%.20f\n",z);
这段代码的输出是:
3.141593
3.141593
3.141593
3.14159274101257324219
3.14159264351134881466
3.14159264351134881466
查看最后一个输出行。我读过long double 的精度为小数点后 19 位。但在这里我得到小数点后 15 位的精度。所以在我的电脑中double 和long double 没有区别。我在 CentOS 上使用 linux 内核 2.6.32-358.el6.x86_64。
我的 C 编译器是gcc version 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC)
为什么会这样?如果它取决于计算机硬件/架构,我如何购买我的 linux 机器,其中 long double 比 double 更精确? 它是否也取决于我的 C 编译器?如果是,我该如何选择我的 C 编译器?
对于float,取值范围是1.2E-38 to 3.4E+38。我不明白这个。从上面的例子我们看到我们不能在float 变量中正确地存储一个小数,例如 3.1415926。我的机器将仅在 float 变量中正确存储 3.141592。所以我丢失了最后的第 7 位数字,这里是 6。那为什么我们说float range is 1.2*10^-38 呢?
是不是我们不能存储多达 10^-38 但我们可以为 C 中的 float 变量存储多达 10^-6 ?
【问题讨论】:
-
这在 x64 上是预期的。为什么你觉得双倍不够。尽管您根本不了解浮点的工作原理,但从您的 cmets 来看。在继续之前,您必须正确处理。您需要了解值存储为尾数和指数。
-
请注意,您应该将
z格式化为%Lf(尽管如果使用sizeof(double) == sizeof(long double),您将侥幸成功)。 -
要检查 double 和 long double 是否具有相同的精度,请检查 sizeof(double) 和 sizeof(long double)。如果大小相等,则两者都表示相同的精度。这类似于 int 和 long int 都占用 4 个字节的情况,而 long long int 是 8 个字节并且范围更大。
-
@prashanthns:大小相等并不意味着精度或范围相等。实现可以选择使用更广泛的双精度格式,例如更好地对齐它们,但对它们执行比
long double更快的操作。只有一种方法:比较提供的宏。 -
@KamiKaze:通常情况下 - 计算不同的架构。大多数 C 平台仍然使用 16 位
int或 32 位 CPU。int和long的 Wrt 大小,有一个众所周知的反例:POSIX64(例如 Linux),即 I32LP64。
标签: c gcc floating-point numerical-methods