【问题标题】:Multiplying float with double overflow in C++在 C++ 中将浮点数与双溢出相乘
【发布时间】:2020-08-25 17:40:15
【问题描述】:

我对这个警告的意义有点困惑:
算术溢出:对 4 字节值使用运算符“”,然后将结果转换为 8 字节值。在调用 '' 运算符之前将值转换为更广泛的类型以避免溢出。

#include <iostream>
using std::cin;
using std::cout;
using std::ios_base;

int main() {
    cout.setf(ios_base::fixed, ios_base::floatfield);
    double mints = 10.0 / 3.0;
    const float c_MILLION = 1e6;
    cout << "\n10 million mints: " << 10 * c_MILLION * mints;

    cin.get();
}

根据我的理解,当我们将浮点值与双精度值相乘时,我们基本上是将 4 字节值乘以 8 字节值,因此根据我阅读的链接,我们将失去一些精度:

http://www.cplusplus.com/articles/DE18T05o/#:~:text=Overflow%20is%20a%20phenomenon%20where,be%20larger%20than%20the%20range

但是,当我输出这个时,我得到一个双精度值
https://i.stack.imgur.com/EOQzm.png

如果是这样,如果 c_MILLION 自动将其更改为双精度结果,为什么还要提醒我将其强制转换为双精度值?无论如何,它无法将 8 字节值转换为 4 字节值。那么,既然它已经让我们摆脱了这个麻烦,为什么还要费心去警告程序员呢?
或者它也可以将 8 字节值转换为 4 字节值。如果是这样,它如何确定要打印的类型?这是一个我无法从我阅读的链接中找到答案的问题。
如果它自动将结果转换为 8byte 值,那么显示此警告的意义何在?
这是警告:
https://i.stack.imgur.com/L2szy.png

严重性代码说明项目文件行抑制状态 警告 C26451 算术溢出:对 4 字节值使用运算符“*”,然后将结果转换为 8 字节值。在调用运算符'*'之前将值转换为更广泛的类型以避免溢出(io.2)

问题是我将int 值与double 值相乘。但是当它自动将intdouble 的乘法转换为double 值时,警告仍然不存在。

【问题讨论】:

  • 你用的是什么编译器?我无法收到此警告。 AFAICT,您的代码很好。
  • "...为什么要提醒我..."什么警告 - 直播 - godbolt.org/z/joxG6K
  • 我正在使用 g++ 编译器和 Visual Studio 2019 IDE。我收到此警告算术溢出:在 4 字节值上使用运算符 *,然后将结果转换为 8 字节值。在调用运算符 * 之前将值转换为更宽的类型以避免溢出。
  • 我不知道这个问题被否决的原因,至少给我一个为什么这个问题被否决的原因?
  • @RichardCritten 我已经上传了警告图片。

标签: c++ floating-point truncate


【解决方案1】:

警告是因为这个乘法:10 * c_MILLIONc_MILLION 的某些值可能会丢失一些精度,如果首先将 c_MILLION 转换为 double,这些精度不会丢失。由于这个乘法的结果被转换为double,一个错误的程序员可能会假设如果操作数首先是double,则没有超出预期的精度丢失。因此发出警告。

【讨论】:

  • 这没有意义。如果c_MILLION 是双精度数,则适用相同的参数。
  • @ProgrammingRage 将intfloat 相乘不会 得到double。这种误解可能是警告存在的原因。
  • @NathanOliver:编译器说“嘿,你在一个四字节的桶中做这个算术,然后把它放在一个八字节的桶里。首先从 8 字节存储桶开始,您可能会得到更好的结果。”如果c_MILLIONdouble,那么您已经在一个八字节的桶中;没有机会将较早的操作扩大到较晚的大小,因此没有相应的警告。
  • @ProgrammingRage:如果您将int 乘以floatint 乘以doublefloat 乘以双精度或@,编译器显然不会发出警告987654338@ 由double 然后由double。警告intfloatdouble 的原因是编译器作者正在计算,只要你最终去double,为什么不先使用它呢?使用int 乘以double(从float 转换)然后乘以double 可能会得到更准确的结果。所以它会告诉你这个机会。
  • @ProgrammingRage:所以 int 乘以 float 本身不会收到警告,因为您最终得到的是 float,编译器没有理由认为您以后可能需要更高的精度。只是intfloatdouble 有机会更早地扩大算术。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
  • 1970-01-01
  • 1970-01-01
  • 2018-10-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多