1

我的教科书 - C in a Nutshell, ISBN 978-0596006976

强制转换部分,示例中的代码显示 C 舍入错误:

代码:

#include <stdio.h>

int
main()
{
  long l_var = 123456789L;
  float f_var = l_var;

  printf("The rounding error (f_var - l_var) is %f\n", f_var - l_var);

  return 0;
}

然后它输出的值只有 0.000000

似乎在投射那些文字时没有精度问题

使用 gcc(v4.4.7) 命令

gcc -Wall file.c -o exec

GNU 是否提供了一种更好的方法来解决该章中提到的问题

或者只是一些不严格接近舍入误差问题的设置?

4

3 回答 3

4

我不知道这一章要告诉你什么,但是:

float f_var = l_var;

我们可以说f_var(float)l_var。现在表达:

f_var - l_var

由于这对 along和 a 进行操作float,因此long将转换为 a float。所以编译器会这样做:

f_var - (float)l_var

这与以下内容相同:

(float)l_var - (float)l_var

无论转换的任何舍入,它都是零。

于 2013-11-13T15:37:45.947 回答
2

我无权访问这本书。

我的猜测是,该示例试图告诉您,如果将 32 位整数分配给 32 位浮点数,则可能会由于截断(舍入错误)而丢失位:32 位浮点数只有 23 位有效数,而某些位可能相应地在分配过程中丢失。

显然,书中的示例代码是伪造的。这是演示截断错误的代码:

#include <stdint.h>
#include <stdio.h>

int main() {

  int32_t l_var = 123456789L;

  /* 32 bit variable, 23 bit significand, approx. 7 decimals  */
  float f_var = l_var; 

  double err = (double) f_var - (double) l_var;

  printf("The rounding error (f_var - l_var) is %f\n", err);

  return 0;
}

这打印

The rounding error (f_var - l_var) is 3.000000

在我的机器上。

于 2013-11-13T16:14:10.587 回答
0

如果两个值都转换为浮点数,0 是您获得的值,如果将它们转换为其他值,您将获得其他值。并且标准允许使用计算类型所需的更广泛的浮点表示 (*)。在这里使用它特别诱人,因为必须将结果转换为双精度才能传递给 printf。

我的 gcc 版本在为 x86_64(gcc 的 -m64 参数)编译时没有使用该津贴,而在为 x86(-m32 参数)编译时正在使用它。当您知道对于 64 位,它使用 sse 指令可以轻松地以浮点数进行计算时,这是有道理的,而在编译 32 位时,它使用的是较旧的“8087”堆栈模型,它不能轻易做到这一点。


(*) C90 中 6.2.1.5 的最后一段,C99 中的 6.3.1.8/2,C11 中的 6.3.1.8/2。我给出了最新的文本(如n1539)

浮动操作数的值和浮动表达式的结果可以用比类型要求更高的精度和范围来表示;类型不会因此而改变。

正如 Pascal Cuoq 所指出的,从 C99 开始,您可以使用FLT_EVAL_METHOD进行测试。

于 2013-11-13T16:22:52.173 回答