分配给“float”时,附加“f”何时会更改浮动常量的值?

f在将常量分配给 a 时,将an应用于浮点常量似乎没有什么区别float

int main(void) {
  float f;
  //  1 2345678901234567
  f = 3.1415926535897932;
  printf("%.6a  %.8f  pi 3.1415926535897932n", f, f);
  f = 3.1415926535897932f;              // v
  printf("%.6a  %.8f  pi 3.1415926535897932fn", f, f);
}

有或没有f,值是一样的

// value       value          code 
0x1.921fb6p+1  3.14159274  pi 3.1415926535897932
0x1.921fb6p+1  3.14159274  pi 3.1415926535897932f

为什么要使用f

回答

这是每个回答你自己的问题的自我回答。

附加 af很少有区别,但在某些情况下确实如此。当f也被省略时,启用良好的编译器可能会发出警告。

  float f = 3.1415926535897932;  // May generate a warning

警告:从“double”到“float”的转换会将值从“3.1415926535897931e+0”更改为“3.14159274e+0f”[-Wfloat-conversion]


要产生价值差异,请注意潜在的双舍入问题。

第一次舍入是由于代码的文本被转换为浮点类型。

结果要么是最近的可表示值,要么是与最近的可表示值紧邻的较大或较小的可表示值,以实现定义的方式选择。C17dr § 6.4.4.2 3

一种非常常见的实现定义方式是将源代码文本转换为最接近的double(没有f)或最接近floatf后缀。质量较差的实现有时是第二个最佳选择。

doubleFP 常数分配给 afloat会导致另一次舍入。

如果要转换的值在可以表示但不能精确表示的值范围内,则结果是最接近的较高或最接近的较低可表示值,以实现定义的方式选择。C17dr § 6.3.1.4 2

一种非常常见的实现定义方式是将 the 转换double为最接近的float- ties to even。(编译时间舍入可能受各种编译器设置的影响。)

双舍入值变化

考虑源代码使用的值非常接近2 个float值之间的中间值的情况。

如果没有f,则将代码四舍五入到 adouble可能会导致值恰好介于 2float秒之间。doublefloatthen的转换可能不同于“with an f”。

使用f,转换结果最接近float

#include <math.h>
#include <stdio.h>
int main(void) {
  float f;
  f = 10000000.0f;
  printf("%.6a  %.3f  10 millionn", f, f);
  f = nextafterf(f, f + f);
  printf("%.6a  %.3f  10 million - next floatn", f, f);
  puts("");
  f = 10000000.5000000001;
  printf("%.6a  %.3f  10000000.5000000001n", f, f);
  f = 10000000.5000000001f;
  printf("%.6a  %.3f  10000000.5000000001fn", f, f);
  puts("");
  f = 10000001.4999999999;
  printf("%.6a  %.3f  10000001.4999999999n", f, f);
  f = 10000001.4999999999f;
  printf("%.6a  %.3f  10000001.4999999999fn", f, f);
}

输出

0x1.312d00p+23  10000000.000  10 million
0x1.312d02p+23  10000001.000  10 million - next float

// value        value         source code
0x1.312d00p+23  10000000.000  10000000.5000000001
0x1.312d02p+23  10000001.000  10000000.5000000001f // Different, and better

0x1.312d04p+23  10000002.000  10000001.4999999999
0x1.312d02p+23  10000001.000  10000001.4999999999f // Different, and better

舍入模式

当舍入模式为向上、向下或趋向于零时,关于双1舍入的问题不太可能出现。当第二次四舍五入在中途情况下复合方向时,就会出现这种情况。

出现率

当代码不精确地转换double为非常接近 2 个float值之间的中间值时会出现问题 - 因此相对罕见。即使代码常量是十进制或十六进制形式,问题也适用。使用随机常数:大约 2 30中的 1

推荐

很少有主要问题,但f后缀更好地获得最佳值float并安静警告。


1 double在这里是指做某事两次,而不是 type double


以上是分配给“float”时,附加“f”何时会更改浮动常量的值?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>