我一直在寻找与我现在遇到的问题类似的问题,但是我找不到任何东西,也没有找到任何东西,也没有找到其他网站。
#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内的条件不再满足,循环应该结束。
BUT
我无法理解为什么,它没有结束。如果您运行代码,您将看到(您必须快速单击cmd内的某个位置以暂时停止循环)所有步骤都是正确的,可能是一个愚蠢的错误或我看不到的东西,但是现在我不知道我知道在哪里敲我的脑袋了。
感谢您阅读这篇很长的帖子,感谢任何帮助,对不起我糟糕的英语感到抱歉!
答案 0 :(得分:5)
运行此代码段
float value = 2 * 0.3;
if (value == 0.6)
std::cout << "Exactly" << std::endl;
else
std::cout << "Ooops" << std::endl;
你会看到输出类似于
0.600000024
尝试使用epsilon-delta逻辑而不是精确值
if (value >= 0.6 && value <= 0.6001)
答案 1 :(得分:1)
我认为Ceros的评论是对的。由于舍入差异,比较浮点值非常容易出错。
所以常见的方法是使用一些容差值来比较,就像在这个函数中一样。
bool AreEqual(double value1, double value2)
{
double tolerance = 0.0001;
return fabs(value1 - value2) < tolerance;
}
在你的代码中你会改变这样的条件:
while(!AreEqual(Controllo,Controllo2));
答案 2 :(得分:1)
问题在于:
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
中的哪一个不为零,并将其用作分隔符。