在 C++ 中正确转换浮点数
Posted
技术标签:
【中文标题】在 C++ 中正确转换浮点数【英文标题】:Correctly converting floating point in C++ 【发布时间】:2016-10-27 11:13:02 【问题描述】:告诉 C++ 编译器“只警告我不知道的浮点转换”的正确/推荐方式是什么?
在 C 语言中,我将启用与浮点转换相关的警告,然后使用显式 C 样式强制转换来消除与受控制的转换相关的警告。
例如,计算a*a*a - b*b
很容易在单精度浮点中溢出,因此您可能希望以双精度计算它,以后只使用单精度:
double a = 443620.52;
double b = 874003.01;
float c = (float)(a*a*a - b*b);
上述 C 风格的显式转换将使编译器关于从 double
转换为 float
的警告静音。
阅读有关强制转换的 C++ 文档,我得出结论,在 C++ 中执行此操作的正确方法如下:
double a = 443620.52;
double b = 874003.01;
float c = static_cast<float>(a*a*a - b*b);
但是,这真的是在 C++ 中执行此操作的正确方法吗?
我理解 static_cast
语法为 ugly on purpose 背后的基本原理,因此您可以尽可能避免强制转换。
是的,我可以省略显式强制转换为浮动。但是然后我需要禁用告诉我精度损失的编译器警告(否则我会收到许多不相关的警告,这些警告会让人很难注意到真正相关的警告)。如果我禁用 fp 相关的编译器警告,当我在其他代码位置错误地丢失精度时,我将失去被警告的可能性。
那么,在 C++ 中进行浮点转换的正确方法是什么?
【问题讨论】:
【参考方案1】:是的
float c = static_cast<float>(a*a*a - b*b);
是在 C++ 中显式转换为 float 的正确方法。你也可以这样做:
float c = (float)(a*a*a - b*b);
但是使用这样的“C 风格”转换是不好的风格,因为 static_cast
将隐藏比 C 风格更少的错误。
或者,如果你经常这样做,你可以定义一个函数:
inline float flt(double d)return static_cast<float>(d);
然后你可以写:
float c = flt(a*a*a - b*b);
它比原来的 C 更加紧凑(并且将被优化为空)。
【讨论】:
但是从double
到float
的转换在浮点编程中很常见。 static_cast
“丑陋”将是一种不应有的惩罚恕我直言,因为演员不仅是合法的,而且是必要的,而且无论编码风格多么好,都无法避免。
非常感谢,您关于定义函数的建议完全符合我的需求,而且是简洁的 C++ 编码风格。【参考方案2】:
据我所知,有三种不同的方法可以避免警告:
-
C 风格转换
static_cast
构造函数式转换(例如float c = float(a*a*a-b*b)
)
在下面的代码示例中,c1
、c2
和 c3
避免出现警告:
int main()
double a = 443620.52;
double b = 874003.01;
// These three versions avoid the conversion warnings:
float c1 = (float)(a*a*a - b*b);
float c2 = static_cast<float>(a*a*a - b*b);
float c3 = float(a*a*a - b*b);
// Only these two give conversion warnings:
float c4(a*a*a - b*b);
float c5 = a*a*a - b*b;
(void)c1; // Just to avoid unused-variable warnings
(void)c2;
(void)c3;
(void)c4;
(void)c5;
只有c4
和c5
会触发警告。 Check the live demo查看结果。
【讨论】:
以上是关于在 C++ 中正确转换浮点数的主要内容,如果未能解决你的问题,请参考以下文章