C++ 如果(a==b)不';t在for循环中为双打工作
我目前正试图编写一个滴定曲线模拟器。但我在比较两个值时遇到了一些麻烦 我创建了一个小的工作示例,完美地复制了我遇到的bug:C++ 如果(a==b)不';t在for循环中为双打工作,c++,for-loop,C++,For Loop,我目前正试图编写一个滴定曲线模拟器。但我在比较两个值时遇到了一些麻烦 我创建了一个小的工作示例,完美地复制了我遇到的bug: #include <iostream> #include <math.h> using namespace std; int main() { double a, b; a = 5; b = 0; for(double i = 0; i<=(2*a); i+=0.1){ b = i;
#include <iostream>
#include <math.h>
using namespace std;
int main()
{
double a, b;
a = 5;
b = 0;
for(double i = 0; i<=(2*a); i+=0.1){
b = i;
cout << "a=" << a << "; b="<<b;
if(a==b)
cout << "Equal!" << endl;
else
cout << endl;
}
return 0;
}
但是,如果我将迭代增量从I+=0.1
更改为I+=1
或I+=0.5
,我将得到
a=5; b=5Equal!
如你所料
我在linux上使用g++进行编译,没有使用更多的标志,坦率地说,我不知道如何解决这个问题。非常感谢任何指针(甚至是我问题的完整解决方案)。浮点算法是。。。有趣。在大多数语言中,用浮点/双精度测试等式都很烦人,因为它是在IEEE浮点数学中进行的。基本上,如果您可以将表达式计算为5.0,编译器可能会将其计算为4.9999999,因为它是IEEE标准中最接近的可表示数字 因为这些数字略有不同,所以最终会出现一个不等式。因为试图预测编译时将看到的数字是不可维护的,所以您不能/不应该尝试将它们中的任何一个硬编码到源代码中,以测试它们是否相等。作为一项硬性规定,避免直接检查浮点数的相等性 相反,测试它们是否非常接近与以下内容相等:
template<typename T>
bool floatEqual(const T& a, const T& b) {
auto delta = a * 0.03;
auto minAccepted = a - delta;
auto maxAccepted = a + delta;
return b > minAccepted && b < maxAccepted;
}
模板
布尔浮式码头(施工T&a、施工T&b){
自动增量=a*0.03;
自动minAccepted=a-增量;
自动最大接受=a+增量;
返回b>minAccepted&&b
这将检查b是否在a值的+3%或-3%范围内。浮点运算是。。。有趣。在大多数语言中,用浮点/双精度测试等式都很烦人,因为它是在IEEE浮点数学中进行的。基本上,如果您可以将表达式计算为5.0,编译器可能会将其计算为4.9999999,因为它是IEEE标准中最接近的可表示数字 因为这些数字略有不同,所以最终会出现一个不等式。因为试图预测编译时将看到的数字是不可维护的,所以您不能/不应该尝试将它们中的任何一个硬编码到源代码中,以测试它们是否相等。作为一项硬性规定,避免直接检查浮点数的相等性 相反,测试它们是否非常接近与以下内容相等:
template<typename T>
bool floatEqual(const T& a, const T& b) {
auto delta = a * 0.03;
auto minAccepted = a - delta;
auto maxAccepted = a + delta;
return b > minAccepted && b < maxAccepted;
}
模板
布尔浮式码头(施工T&a、施工T&b){
自动增量=a*0.03;
自动minAccepted=a-增量;
自动最大接受=a+增量;
返回b>minAccepted&&b
这将检查b是否在a值的+3%或-3%范围内。与整数不同,将浮点/双精度相乘并将它们相加不会产生完全相同的结果 因此,最好的做法是找出它们之间差异的
abs
是否足够小
如果您对数字的大小有所了解,可以使用常数:
if (fabs(a - b) < EPS) // equal
注:
在代码中,可以使用
std::abs
。对于std::min/max
相同。使用C函数时,代码更清晰/更短。与整数不同,将浮点/双精度相乘并将它们相加不会产生完全相同的结果
因此,最好的做法是找出它们之间差异的abs
是否足够小
如果您对数字的大小有所了解,可以使用常数:
if (fabs(a - b) < EPS) // equal
注:
在代码中,可以使用
std::abs
。对于std::min/max
相同。使用C函数时,代码更清晰/更短。我建议重新构造循环,使用整数进行迭代,然后将整数转换为双精度,如下所示:
double step = 0.1;
for(int i = 0; i*step<=2*a; ++i){
b = i*step;
cout << "a=" << a << "; b="<<b;
if(a==b)
cout << "Equal!" << endl;
else
cout << endl;
}
double step=0.1;
对于(int i=0;i*step,我建议重新构造循环,使用整数进行迭代,然后将整数转换为双精度,如下所示:
double step = 0.1;
for(int i = 0; i*step<=2*a; ++i){
b = i*step;
cout << "a=" << a << "; b="<<b;
if(a==b)
cout << "Equal!" << endl;
else
cout << endl;
}
double step=0.1;
对于(int i=0;i*step.不要在循环条件中使用浮点数…1.0
和0.5
可以使用浮点数表示为有限的精确数字。0.1
另一方面只能由无限浮点数表示,当存储在有限浮点数中时会暴露舍入错误ber.This:@OliCharlesworth,摘自首页:“也许你在某个论坛上寻求帮助,但被指向了一个似乎对你的问题没有帮助的网站。”-猜猜那个链接指向哪里;)。不要在循环条件中使用浮点…1.0
和0.5
可以使用浮点数表示为有限的精确数字。0.1
则只能表示为无限的浮点数,当存储在有限的浮点数中时会暴露舍入错误。这:@OliCharLeVals:从“首页”中可以看出:“也许你在某个论坛上寻求帮助,并指出了一个似乎没有帮助你解决问题的问题。”——猜猜链接指向哪里;)算术定义得很好,在实现标准的所有实现(大多数C++编译器都是)上是可预测的。@IInspectable-有趣。谢谢!我对结果比对原因更感兴趣,但我还是更新了帖子。坏例子:5.0在IEEE 754中是可表示的。4.999999不是。问题包含另一个不可表示的数字0.1。算术定义良好,在所有实现标准的实现中都是可预测的D(大多数C++编译器)“IsCuffTime-有趣的是,我对结果比对这个原因更感兴趣,但是我更新了帖子。坏的例子是IEEE 754中的5。4.9999999是不包含的。这个问题包含另一个不可代表的数字,0.1为什么不使用<代码> STD::ABS<代码>?它在C++中浮点类型过载。STD::ABS是al。很好,代码是l