我写了一个数学计算器,它从用户那里接收一个字符串并解析它。它使用双精度来保存计算时涉及的所有值。解决之后,我会打印它,并使用std::setprecision()
确保输出正确(例如0.9999999
将在打印输出时变为1
。
返回将输出的字符串:
//return true or false if this is in the returnstring.
if (returnString.compare("True") == 0 || returnString.compare("False") == 0) return returnString;
//create stringstream and put the answer into the returnString.
std::stringstream stream;
returnString = std::to_string(temp_answer.answer);
//write into the stream with precision set correctly.
stream << std::fixed << std::setprecision(5) << temp_answer.answer;
return stream.str();
我知道使用双打和浮动时的准确性问题。今天我开始研究代码,以便用户可以比较两个数学字符串。例如,1=1
将评估为true,2>3
false等等。这是通过为比较运算符的每一侧运行我的数学表达式解析器,然后比较答案。
我现在面临的问题是当用户输入1/3*3=1
之类的内容时。当然因为我使用双打,解析器将返回0.999999
作为答案。通常在解决非比较问题时,如前所述,在使用std::setprecision()
的打印时间进行补偿。但是,当比较两个双打时,它将返回false作为0.99999!=1
。我如何在比较双精度时得到它,这种不准确性得到补偿,答案是否正确返回?这是我用来比较数字本身的代码。
bool math_comparisons::equal_to(std::string lhs, std::string rhs)
{
auto lhs_ret = std::async(process_question, lhs);
auto rhs_ret = std::async(process_question, rhs);
bool ReturnVal = false;
if (lhs_ret.get().answer == rhs_ret.get().answer)
{
ReturnVal = true;
}
return ReturnVal;
}
我认为需要进行某种舍入,但我不能100%确定如何正确完成它。如果已经解决了,请原谅我 - 我找不到搜索的内容。谢谢!
答案 0 :(得分:2)
假设answer
是double
,请替换此
lhs_ret.get().answer == rhs_ret.get().answer
与
abs(lhs_ret.get().answer - rhs_ret.get().answer) < TOL
其中TOL
是适当的容差值。
不应将浮点数与==
进行比较,而应检查绝对差值是否小于给定的容差。
需要提到一个难点:双精度的精确度约为16位小数。所以你可以设置TOL=1.0e-16
。这仅在您的数字小于1时才有效。对于16位数字,这意味着公差必须大到1。
因此,您可以假设您的数字小于10e8
,并使用相对较大的容差,例如10e-8
,或者您需要做一些更复杂的事情。
答案 1 :(得分:1)
首先考虑:
作为一个基本的经验法则,double
将是一个大约16dp的值,其中dp是小数位,或1.0e-16
。你需要知道这只适用于小于一(1)IE的数字10.你必须围绕这个事实操作你只能有15dp EG:10.0e-15
等等...由于计算机在基数2中计数,而人数在基数10中计算,某些值永远无法在&#34;大多数&#34; 现代操作系统使用的位范围内正确表达。
这可以通过以二进制或基数2表示0.1无限长的事实来突出显示。
因此,您不应该通过==
运算符比较有理数。相反,&#34;去&#34;常规使用的解决方案是:
您实施&#34;足够接近&#34; 解决方案。 IE:您将epsilon定义为一个值,例如:epsilon = 0.000001
,并说明(value a - value b) < epsilon == true
。我们所说的是if a - b is within e
,对于我们计划的所有意图和目的,它足够接近被视为真实。
现在为epsilon选择一个值,这一切都取决于您需要的准确度。例如,与2D侧滚动平台游戏相比,可以假设您需要高水平的结构工程精度。
在您的情况下,您要替换代码的第7行的解决方案:
(lhs_ret.get().answer == rhs_ret.get().answer)
带
abs(lhs_ret.get().answer - rhs_ret.get().answer) < epsilon
其中abs是绝对值。 IE忽略值lhs
的符号。
有关更多背景信息,我强烈推荐这个关于麻省理工学院开放课件的讲座,该课程以易于理解的方式解释。