定位由于整数除法引起的数值误差
Locating numerical errors due to Integer division
是否有 g++ 警告或其他工具可以识别整数除法(截断为零)? 我有数千行代码,其中的计算不可避免地会出现数值错误,通常是由于需要定位的"float = int/int"。 我需要一种合理的方法来找到这些。
试试-Wconversion
.
来自 gcc 的手册页:
警告可能出现的隐式转换 更改值。这包括 实数和整数之间的转换, 如"abs (x)",当"x"为"双倍"时; 已签名和 之间的转换 无符号,例如"未签名的 UI = -1";和 转换为较小的类型,例如 "sqrtf (M_PI)"。不要警告 显式转换,如"abs ((int) x)" 和"UI = (无符号) -1",或者如果 值不会因转换而改变 就像在"腹肌(2.0)"中一样。 关于以下方面的警告 已签名和 之间的转换 无符号整数可以通过以下方式禁用 使用 -Wno-sign-conversion。
对于C++,还要警告转化 在"NULL"和非指针类型之间; 令人困惑的重载分辨率 用户定义的转换;和 永远不会使用类型的转化 转换运算符:转换为 "void",相同类型,基类或 对它们的引用。关于以下方面的警告 已签名和 之间的转换 无符号整数由 默认为C++,除非 -显式启用 wsign 转换。
对于以下示例程序(test.cpp
),我得到错误test.cpp: In function ‘int main()’:
test.cpp:7: warning: conversion to ‘float’ from ‘int’ may alter its value
。
#include <iostream>
int main()
{
int a = 2;
int b = 3;
float f = a / b;
std::cout << f;
return 0;
}
我很难称这些数字错误。 您请求整数计算,并获得了用于整数计算的正确数字。 如果这些数字不可接受,则要求浮点计算:
int x = 3;
int y = 10;
int z = x / y;
// "1." is the same thing as "1.0", you may want to read up on
// "the usual arithmetic conversions." You could add some
// parentheses here, but they aren't needed for this specific
// statement.
double zz = 1. * x / y;
此页包含有关 g++ 警告的信息。 如果您已经尝试过-Wall
那么唯一剩下的可能是此链接中的警告。 再看一眼-Wconversion
可能会解决问题。
注意:已完全编辑响应。
关于 gcc -Wconversion
的评论:
将浮点变量的类型从 float
更改为 double
会使警告消失:
$ cat 'file.cpp'
#include <iostream>
int main()
{
int a = 2;
int b = 3;
double f = a / b;
std::cout << f;
}
使用 $ g++-4.7 -Wconversion 'file.cpp'
进行编译不会返回任何警告(如$ clang++ -Weverything 'file.cpp'
)。
解释:
使用类型 float
时不会返回警告,因为整数算术完全有效,而是因为float
无法存储所有可能的int
值(较大的值不能由float
捕获,而只能由double
捕获)。因此,在浮点数的情况下将 RHS 分配给 f
时,值可能会发生变化,但在双精度的情况下则不会。明确说明:返回警告不是因为int/int
,而是因为分配float = int
。
为此,请参阅以下问题:当 java 中大小相同时,浮点数和整数数据类型之间有什么区别,将整数存储为浮点数和舍入以用于 int -> 浮点数 -> int 往返转换
但是,当使用float
-Wconversion
时,对于识别受影响的可能行仍然有用,但并不全面,实际上并不打算这样做。出于-Wconversion
的目的,请参阅 docs/gcc/Warning-Options.html 和此处 gcc.gnu.org/wiki/NewWconversion
可能感兴趣的也是在讨论"隐式强制转换整数计算以浮点C++"
查找此类错误的最好方法是进行非常好的单元测试。所有替代方案都不够好。
看看这个叮叮当当的检测。
它捕获了这样的情况:
d = 32 * 8 / (2 + i);
d = 8 * floatFunc(1 + 7 / 2);
d = i / (1 << 4);
- 为什么在浮点中从大到小会引入更多的误差
- 在除法中不需要四舍五入
- 在TFHE(完全快速同态加密)上执行除法
- 使用 int 表示浮点除法 C++
- 而循环:简单的除法程序输出零,不明白为什么
- 余数除法和不允许除以零 (c++) 时遇到问题
- 如何确定涉及 C++ 中除法的算术表达式的数据类型
- 如何使用除法和for_each?
- 基于相邻元素 c++ 的分段误差范围的循环
- C++:奇怪的除法输出
- 分配给浮点数的积分文字除法 - 为什么结果是错误的?
- 除法函数返回错误的值
- QImage::p ixel 和 QImage::setPixel 坐标超出范围误差
- 检查向量是否使用除法和阻抗算法进行排序
- 将误差线添加到 VTK 二维散点图
- 动态矩阵特征分解过程中的误差
- 不使用算术运算符的除法
- C++编译器能在编译时计算出文字的除法结果吗
- 转换为非标量误差是什么意思?我该如何解决?
- 定位由于整数除法引起的数值误差