在将常量分配给 f
时,将 float
应用于浮点常量似乎没有什么区别。
int main(void) {
float f;
// 1 2345678901234567
f = 3.1415926535897932;
printf("%.6a %.8f pi 3.1415926535897932\n", f, f);
f = 3.1415926535897932f; // v
printf("%.6a %.8f pi 3.1415926535897932f\n", f, f);
}
有或没有 f
,值是一样的// value value code
0x1.921fb6p+1 3.14159274 pi 3.1415926535897932
0x1.921fb6p+1 3.14159274 pi 3.1415926535897932f
为什么要使用 f
?
最佳答案
这是每个 Answer Your Own Question 的自我回答.
附加 f
使常数 a float
有时会产生值(value)差异。
类型差异:double
至 float
.
当 f
出现时,启用良好的编译器可能会发出警告。也省略了。
float f = 3.1415926535897932; // May generate a warning
warning: conversion from 'double' to 'float' changes value from '3.1415926535897931e+0' to '3.14159274e+0f' [-Wfloat-conversion]
要产生值(value)差异,请注意潜在风险 double rounding问题。
第一次舍入是由于代码的文本被转换为浮点类型。
the result is either the nearest representable value, or the larger or smaller representable value immediately adjacent to the nearest representable value, chosen in an implementation-defined manner. C17dr § 6.4.4.2 3
一种非常常见的实现定义方式是将源代码文本转换为最接近的
double
(没有 f
)或最接近的 float
与 f
后缀。质量较差的实现有时是第二个最佳选择。分配
double
FP 常数为 float
导致另一个舍入。If the value being converted is in the range of values that can be represented but cannot be represented exactly, the result is either the nearest higher or nearest lower representable value, chosen in an implementation-defined manner. C17dr § 6.3.1.4 2
一种非常常见的实现定义方式是转换
double
到最近的 float
- 连系。 (编译时间舍入可能受各种编译器设置的影响。)双舍入值更改
考虑源代码使用非常接近 2
float
中间值的情况。值。没有
f
, 代码四舍五入为 double
可能会导致值正好介于 2 float
之间s。 double
的转换至 float
那么可能不同于“带有 f
”。与
f
,转换结果最接近 float
.#include <math.h>
#include <stdio.h>
int main(void) {
float f;
f = 10000000.0f;
printf("%.6a %.3f 10 million\n", f, f);
f = nextafterf(f, f + f);
printf("%.6a %.3f 10 million - next float\n", f, f);
puts("");
f = 10000000.5000000001;
printf("%.6a %.3f 10000000.5000000001\n", f, f);
f = 10000000.5000000001f;
printf("%.6a %.3f 10000000.5000000001f\n", f, f);
puts("");
f = 10000001.4999999999;
printf("%.6a %.3f 10000001.4999999999\n", f, f);
f = 10000001.4999999999f;
printf("%.6a %.3f 10000001.4999999999f\n", 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
舍入模式当舍入模式向上、向下或趋向于零时,关于 double1 舍入的问题不太可能出现。当第二次四舍五入在中途情况下复合方向时,就会出现这种情况。
出现率
当代码不准确地转换为
double
时会出现问题非常接近 2 float
的中途值 - 所以相对少见。即使代码常量是十进制或十六进制形式,问题也适用。使用随机常数:大约 230 分之一。推荐
很少是主要问题,但
f
后缀更好地获得 float
的最佳值并安静警告。1 double 这里指的是做两次某事,而不是类型
double
.
关于c - 分配给 'f' 时,附加 `float` 何时会更改 float 常量的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66631288/