C++做 - 虽然条件满足时无限循环(不明白为什么)
我一直在寻找类似于我现在遇到的问题的小时数,但我找不到任何东西,也找不到任何东西这里或其他网站。C++做 - 虽然条件满足时无限循环(不明白为什么)
#include <iostream>
using namespace std;
int main()
{
double Numero=0, ParteDecimale=0, Controllo=0, Controllo2=0;
int ParteIntera=0;
string Var1="1", Var0="0", NumeroFinale;
cout<<"\n\n\tBenvenuto, questo programma ti consente di convertire la parte\n"
"\tdecimale di un numero in sistema binario. Per iniziare, inserisci un numero: ";
cin>>Numero;
cout<<Numero<<" Numero\n\n"<<endl; //
ParteIntera=Numero; //casting implicito, in modo da poter isolare esclusivamente la parte decimale del numero inserito.
cout<<ParteIntera<<" ParteIntera\n\n"<<endl; //
ParteDecimale=Numero-ParteIntera; //Isolamento della parte decimale
cout<<ParteDecimale<<" ParteDecimale\n\n"<<endl; //
Controllo2=ParteDecimale;
do{
ParteDecimale=ParteDecimale*2; //Moltiplicazione della parte decimale per due
cout<<"\n\nParteDecimaleCiclo "<<ParteDecimale<<endl; //
if(ParteDecimale<1){
NumeroFinale=NumeroFinale+Var0;
cout<<"\n\nNumeroFinaleMin1 "<<NumeroFinale<<endl; //
}
else{
NumeroFinale=NumeroFinale+Var1;
cout<<NumeroFinale<<" NumeroFinaleMagg1\n\n"<<endl; //
ParteDecimale-=1;
cout<<ParteDecimale<<" ParteDecimaleMagg1\n\n"<<endl;
}
Controllo=ParteDecimale;
cout<< "\n\nCONTROLLO " <<Controllo; //
cout<<"\n\nNUMERO "<<Numero; //
}
while(Controllo!=Controllo2);
cout<<NumeroFinale<<endl;
}
很抱歉,如果代码是凌乱的,但是当我看到它并没有如预期工作,我决定输出的每一个值与流程跟着,这是奇怪的事情。该代码的作用完全一样预期和结果都是正确的,即使条件满足,它也拒绝退出do-while循环。
例如:
-I输入“12.2”时,程序存储中的“ParteIntera”变量内的数目(它是一个int,我这样做,以去除小数部分);在“ParteDecimale”中存储“Numero-ParteIntera”(Numero是我在开头输入的输入内容),此时“ParteDecimale”等于0.2;
“ParteDecimale”的值存储在“Controllo2”中;
- 这里启动了Do-While循环,基本上是“ParteDecimale * 2”,所以它是“0.4”;
它检查ParteDecimale是大于还是小于1,并根据它执行if语句内的istructions;
- 从if语句中获得的“ParteDecimale”的值存储在“Controllo”中(在本例中为0.4);
- 检查条件,在这种情况下,“Controllo”和“Controllo2”仍然不同,因此循环重新开始;
在某一点ParteDecimale将为0.6,所以当循环开始时ParteDecimale成为1.2(0.6 * 2)。由于它大于1,所以执行else语句并且ParteDecimale变成0.2(1.2-1)。此时“Controllo”和“Controllo2”都是0.2,所以do-while内部的条件不再满足,循环应该结束。
但是
我不明白为什么,它没有结束。如果你运行代码,你会看到(你必须快速点击cmd内的某个地方暂时停止循环),所有步骤都是正确的,可能是一个愚蠢的错误或者我看不见的东西,但是现在我不'不知道该把我的头撞到哪里去了。
感谢您阅读这篇很长的文章,任何帮助表示赞赏,对不起我的英文不好!
运行这段代码
float value = 2 * 0.3;
if (value == 0.6)
std::cout << "Exactly" << std::endl;
else
std::cout << "Ooops" << std::endl;
而且你会看到输出是一样的东西
0.600000024
尝试使用的ε-Δ逻辑,而不是精确值
if (value >= 0.6 && value <= 0.6001)
谢谢,正如你所看到的,我对C++相当陌生,但我仍然不了解所有的基础知识。非常感谢您指点我正确的方向! –
我认为Ceros在他的评论中是正确的。由于四舍五入的差异,比较浮点值非常容易出错。
所以常用的方法是使用一些公差值来比较,就像在这个函数中一样。
bool AreEqual(double value1, double value2)
{
double tolerance = 0.0001;
return fabs(value1 - value2) < tolerance;
}
在你的代码会改变的情况是这样的:
while(!AreEqual(Controllo,Controllo2));
是的我很肯定Ceros是对的,我不知道两个浮点值之间的比较不是最好的解决方案。谢谢你的回复! –
的问题是在这里:
while(Controllo!=Controllo2);
你期望得到相等的变量是double
类型。浮点数不能完全在计算机中表示。
它们并非完全用铅笔在纸上计算,但我们倾向于认为两个值相等时,他们的第一个小数相等。电脑不这样工作。 Controllo == Controllo2
只有当两个变量具有完全相同的值时,将其最低有效位数加起来。如果不告诉他们这样做,计算机不会做任何舍入。
解决方案很简单(它也是您实现的数学算法的一部分):循环直到两个值足够接近另一个。这意味着,停止当两个值的绝对差值大于一个很小的值越小你提前采摘:
while(fabs(Controllo - Controllo2) > 0.0001);
如果你预先知道或大或小是Controllo
和Controllo2
的值,那么你可以挑一个常数值并用于比较。在我上面的示例中,这是0.0001
,它适用于大数值Controllo
和Controllo2
。如果Controllo
和Controllo2
的值为0.001
或更小的值,则应使用更小的值。
当你不能提前告诉多大或者多小,你比较,你可以检查它们的相对差异值:
while(fabs((Controllo - Controllo2)/Controllo2) > 0.0001);
(假设Controllo2
不为零)。该公式可以在一个函数中提取,该函数可以检查Controllo
和Controllo2
中的哪一个不为零,并将其用作分频器。
真棒解释,非常感谢你!我会尝试在这里发布的所有例子,直到我找到适合我正在尝试做的事情。非常感谢您的时间! –
再次抱歉,我只是试图按照您的代码实现您的代码,但它仅适用于0.2的倍数。我的意思是,如果我插入0.1或0.3作为输入不起作用,但它与0.2; 0.4; 0.6; 0一起使用。8等等!你能解释我为什么吗?我尝试了一些有价值的东西,但我无法得到它 –
解决此类问题的正确工具是您的调试器。在*堆栈溢出问题之前,您应该逐行执行您的代码。如需更多帮助,请阅读[如何调试小程序(由Eric Lippert撰写)](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/)。至少,您应该\编辑您的问题,以包含一个[最小,完整和可验证](http://*.com/help/mcve)示例,该示例再现了您的问题,以及您在调试器。 –
永远不要比较'=='两个浮点值。他们的第n小数可能会不同。尝试使用epsilon三角洲这样的事情。 – Ceros