C++ 补偿双精度/浮动精度
我已经编写了一个数学计算器,它从用户那里获取一个字符串并对其进行解析。它使用double保存计算时涉及的所有值。解决后,我将其打印出来,并使用C++ 补偿双精度/浮动精度,c++,comparison,precision,C++,Comparison,Precision,我已经编写了一个数学计算器,它从用户那里获取一个字符串并对其进行解析。它使用double保存计算时涉及的所有值。解决后,我将其打印出来,并使用std::setprecision()确保正确输出(例如0.9999999将在打印输出时变为1) 返回将被输出的字符串: //return true or false if this is in the returnstring. if (returnString.compare("True") == 0 || returnString.compare(
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();
我认为需要进行某种舍入,但我不能100%确定如何正确完成。如果已经解决了这个问题,请原谅我-我无法通过搜索找到太多。谢谢!假设
答案是双倍的,请替换这个
lhs_ret.get().answer == rhs_ret.get().answer
与
abs(lhs_ret.get().answer-rhs_ret.get().answer)
其中,TOL
是一个合适的公差值
绝不应将浮点数与==
进行比较,而应检查绝对差值是否小于给定公差
有一个困难需要提及:双精度约为16位小数。因此,您可以设置TOL=1.0e-16
。这仅在数字小于1时有效。对于16位数字,这意味着公差必须与1一样大
因此,要么您假设您的数字小于say10e8
,并使用相对较大的公差,如10e-8
,要么您需要做更复杂的事情。假设answer
是一个double
,则将其替换
lhs_ret.get().answer == rhs_ret.get().answer
与
abs(lhs_ret.get().answer-rhs_ret.get().answer)
其中,TOL
是一个合适的公差值
绝不应将浮点数与==
进行比较,而应检查绝对差值是否小于给定公差
有一个困难需要提及:双精度约为16位小数。因此,您可以设置TOL=1.0e-16
。这仅在数字小于1时有效。对于16位数字,这意味着公差必须与1一样大
因此,要么您假设您的数字小于say10e8
,并使用相对较大的公差,如10e-8
,要么您需要做更复杂的事情。首先考虑:
作为基本经验法则,double
将是一个大约16dp的值,其中dp是小数位,或1.0e-16
。您需要注意,这只适用于小于一(1)的数字IE for 10.n您必须围绕这一事实操作,您只能有15dp,例如:10.0e-15
等等……由于计算机以2为基数计数,而人们以10为基数计数,一些值永远无法在“大多数”现代操作系统使用的位范围内正确表示
用二进制或基数2表示0.1是无限长的,这一事实可以突出说明这一点
因此,您永远不应该通过=
运算符比较有理数。相反,通常使用的“转到”解决方案是:
您实现了一个“足够接近”的解决方案。即:您将epsilon定义为一个值,例如:epsilon=0.000001
,并且您声明如果(值a-value b)
。我们要说的是如果a-b在e
之内,对于我们程序的所有意图和目的,它的接近程度足以被视为true
现在选择epsilon的值,这完全取决于你的目的需要有多精确。例如,你可以假设与2D侧滚平台游戏相比,你需要高水平的结构工程精度
您的解决方案是替换代码的第7行:
(lhs_ret.get().answer==rhs_ret.get().answer)
与
abs(lhs_ret.get().answer-rhs_ret.get().answer)
其中abs是绝对值。即忽略值的符号lhs
关于更多的内容,我强烈推荐这节麻省理工学院开放式课程,它以一种易于理解的方式来解释
首先考虑:
作为基本经验法则,double
将是一个大约16dp的值,其中dp是小数位,或1.0e-16
。您需要注意,这只适用于小于一(1)的数字IE for 10.n您必须围绕这一事实操作,您只能有15dp,例如:10.0e-15
等等……由于计算机以2为基数计数,而人们以10为基数计数,一些值永远无法在“大多数”现代操作系统使用的位范围内正确表示
用二进制或基数2表示0.1是无限长的,这一事实可以突出说明这一点
因此,您永远不应该通过=
运算符比较有理数。相反,通常使用的“转到”解决方案是:
您实现了一个“足够接近”的解决方案。即:您将epsilon定义为一个值,例如:epsilon=0.000001
,并且您声明如果(值a-value b)
。我们要说的是如果a-b在e
之内,对于我们程序的所有意图和目的,它的接近程度足以被视为true
现在选择epsilon的值,这完全取决于你的目的需要有多精确。例如,你可以假设与2D侧滚平台游戏相比,你需要高水平的结构工程精度
您的解决方案是替换代码的第7行:
(lhs_ret.get().answer==rhs_ret.get().answer)
与
abs(lhs_ret.get().answer-rhs_ret.get().answer)
其中abs是绝对值。即忽略值的符号lhs
关于更多的内容,我强烈推荐这节麻省理工学院开放式课程,它以一种易于理解的方式来解释
你知道的double
abs(lhs_ret.get().answer - rhs_ret.get().answer) < TOL