在复合赋值运算符中强制转换

Casting in a compound assignment operator?

本文关键字:转换 复合 赋值运算符      更新时间:2023-10-16

我的代码,简化为本质,归结为:

int x = 5;
x *= 0.5;

使用 Visual Studio 编译它,我收到关于可能丢失数据的警告 C4244 - 当然,因为(简化)将 int 乘以双精度会导致双精度,然后将其转换为 int,丢失非整数部分。

我的问题是,是否有C++语法来指示这是预期行为,以便使警告静音(我知道编译指示按钮/弹出以禁用警告,我认为更清楚地表明这实际上是预期行为,并且我不只是抑制警告)。

长格式是在乘法后显式强制转换,如下所示:

x = (int)(x * 0.5);

但是复合运算符表示法更易于阅读。

那么,有没有办法像这样投射呢?我尝试在我能想到的每个位置都放置"(int)",但它们似乎都无效C++ :(

与其乘以 0.5,不如除以 2。对于两个int将使用整数除法,并且不会有任何警告。

如果你真的想乘以浮点数/双精度数,不要使用int来存储结果。

警告已到位 - 您应该收到数据丢失的警告。

避免警告的任何方法都涉及使用明确表达您的意图的语法。这可以通过以下方式完成:

  1. 创建一个函数,它做你想做的事。
  2. 不要使用一元运算符。相反,请使用二进制运算符,并显式截断结果:x = static_cast<int>(x * 0.5);

使用一元运算符*您无法轻松禁止显示警告,因为该运算符旨在以清晰明了的方式成为用户,不涉及强制转换 - 并且您的案例不满足此要求。所以你不能这样做是一件事。

根据OP的评论,最好根据您想要的舍入行为类型(有偏见/无偏见)使用<cmath>中的适当函数。

例如floor通常进行偏置舍入(偏向负无穷大,因为它总是选择较小的整数),即 floor( -7.5 )会给你-8,如果你想要一个对称的舍入,你需要自己滚动,即希望floor( -7.5 ) -7(如floor( 7.5 )给出7)。

但是,可以调整round以产生无偏的舍入。通常,它会从round( 10.3 )产生1011round( 10.6 )(或更高)产生。中间四舍五入(平局)仍然存在问题,即round( 10.5 )应该提供什么(它通常会产生11)。如果此行为不适合您,您可能需要查找一些替代方案,例如银行家的舍入/替代四舍五入等。

int 和浮点数相乘的结果是浮点数

如果要将 int 转换为浮点数,则可能需要舍入浮点数以删除十进制值。如果只是投射它,则可能会出现舍入误差。

例如,此函数进行舍入(还有其他舍入数字的方法):

int round(float x)
{
  return static_cast<int>((x > 0.5) ? ceil(x) : floor(x));
} 

然后你只需要这样称呼它:

  int x = 5;
  float y = 0.33f;
  x = round(x * y);

而且您没有警告浮点数已正确舍入并转换为整数

我没有适合四

舍五入的*=运算符的解决方案,因此使用此解决方案,您将不得不更换*=