【问题标题】:Format specifier %Lf for long double in C is not working as if expectedC 中 long double 的格式说明符 %Lf 未按预期工作
【发布时间】:2016-05-11 03:21:01
【问题描述】:

作者在学习在线视频中的C要领时,分享了下面的代码,以找出float、double和long double之间的区别。 我在运行在 64 位 Windows 10 笔记本电脑上的 Eclispse 中运行了这个程序。

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

int main(void) {
puts("Floating point type usage in C:");

// Floating point types
float           floatNumber;
double          doubleNumber;
long double     longDoubleNumber;

// Size of floating point types
//lu - Stands for "unsigned decimal integer" and "long"
printf("Storage size for unsigned float : %lu  bytes \n", sizeof(float));
printf("Storage size for double :         %lu  bytes \n", sizeof(double));
printf("Storage size for long double :   %lu  bytes \n", sizeof(long double));

floatNumber = 2.0/3.0;
doubleNumber = 2.0/3.0;
longDoubleNumber = 2.0/3.0;

puts("\nCompare precision at 4 decimal points:");
printf("floatNumber      = %1.4f\n", floatNumber);
printf("doubleNumber     = %1.4lf\n", doubleNumber);
printf("longDoubleNumber = %1.4Lf\n", longDoubleNumber);

puts("\nCompare precision at 10 decimal points:");
printf("floatNumber      = %1.10f\n", floatNumber);
printf("doubleNumber     = %1.10lf\n", doubleNumber);
printf("longDoubleNumber = %1.10Lf\n", longDoubleNumber);

puts("\nCompare precision at 30 decimal points:");
printf("floatNumber      = %1.30f\n", floatNumber);
printf("doubleNumber     = %1.30lf\n", doubleNumber);
printf("longDoubleNumber = %1.30g\n", longDoubleNumber);
return 0;
}

不知何故,我没有得到预期的输出。 我已经添加了我在 Eclispse 控制台中得到的输出。 谁能帮我找出问题所在

Floating point type usage in C:
Storage size for unsigned float : 4  bytes 
Storage size for double :         8  bytes 
Storage size for long double :   16  bytes 

Compare precision at 4 decimal points:
floatNumber      = 0.6667
doubleNumber     = 0.6667
longDoubleNumber = 0.0000              //Expected value = 0.6667

Compare precision at 10 decimal points:
floatNumber      = 0.6666666865
doubleNumber     = 0.6666666667
longDoubleNumber = 0.0000000000   //Expected value = 0.6666666667

Compare precision at 30 decimal points:
floatNumber      = 0.666666686534881590000000000000 
doubleNumber     = 0.666666666666666630000000000000
longDoubleNumber = 3.1728895775924853e-317   //This is not the expected value

【问题讨论】:

  • 您使用的是什么编译器和运行时/libc?
  • 试试longDoubleNumber = (long double)2.0/3.0;
  • @sjsam,原始代码中缺少强制转换可能是故意的。无论如何,它并没有解释所呈现的输出。
  • 30 位变体应使用%1.30Lg%1.30Lf,而不是%1.30f。但我怀疑该修复程序能否获得您期望的输出,因为其他 long double 输出也不正确。在我看来,您的编译器或 C 库似乎有问题/不符合标准。
  • @JohnBollinger:或者它可能是编译器/库不匹配。例如。在 Windows 上,msvcrt 假定 long double == double。

标签: c double format-specifiers long-double length-modifiers


【解决方案1】:

我建议您进行一些更正,然后重新运行测试。 首先,我们需要确保所有类型都是正确的,并且不涉及任何促销或其他事情。我们需要改变

floatNumber = 2.0/3.0;
longDoubleNumber = 2.0/3.0;

floatNumber = 2.0f / 3.0f;
longDoubleNumber = 2.0L / 3.0L;

这是不允许将结果提升为 double(在第一种情况下以及在第二种情况下从 double 类型转换为 long double 类型)所必需的,因为最初您的两个操作数在每种情况下都是“double”类型。

其次,你应该摆脱未定义的行为

printf("longDoubleNumber = %1.30g\n", longDoubleNumber);

并在格式字符串中使用适当的 long double 长度说明符。它看起来像这样:

printf("longDoubleNumber = %1.30Lg\n", longDoubleNumber);

通知我们结果。

【讨论】:

  • 虽然这些更改是合理的,但并不清楚它们是否都适合该程序的特定演示目的。但是,更重要的是,尚不清楚您为什么认为这些可以解决 OP 指出的特定输出问题。考虑到早期不正确输出的性质,即使最后建议的更改(实际上是必要的)似乎也不太可能产生正确的输出。
  • @JohnBollinger,我没有说他们会,我说他们“应该”。不过我同意,“可能”这个词更合适。更改的目的是消除类型转换可能产生的副作用。一旦可以说没有,如果问题仍然存在,那么我们可以继续前进。这是我在atm看到的最合理的做法。
  • 即使是“可能”也是不合理的乐观。 没有理由期望建议的更改会解决 OP 的主要问题。
  • @JohnBollinger,很好,随心所欲。
猜你喜欢
  • 2020-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多