我遇到了一些我以前从未见过的东西,非常想了解发生了什么。我试图将一个双精度数转换为2位小数并将该值转换为字符串。在完成演员表演后,我发疯了。
以下是代码:
void formatPercent(std::string& percent, const std::string& value, Config& config)
{
double number = boost::lexical_cast<double>(value);
if (config.total == 0)
{
std::ostringstream err;
err << "Cannot calculate percent from zero total.";
throw std::runtime_error(err.str());
}
number = (number/config.total)*100;
// Format the string to only return 2 decimals of precision
number = floor(number*100 + .5)/100;
percent = boost::lexical_cast<std::string>(number);
return;
}
我没有达到我的预期,所以我做了一些调查。我做了以下事情:
std::cout << std::setprecision(10) << "number = " << number << std::endl;
std::cout << "percent = " << percent << std::endl;
...并获得以下内容:
number = 30.63
percent = 30.629999999999999
我怀疑提升正在做一些有趣的事情。有没有人在这里有任何见解?
说真的,这有多奇怪?!?我要求双倍的10位精度并获得4位数。我要求将这4个数字转换成一个字符串并弄得一团糟。发生了什么事?
答案 0 :(得分:3)
十进制数30.63
无法存储在double类型的对象中。最接近的有效double值(实际存储的值)为8621578536647393 * 2^-48
,在十进制表示法中为30.629999999999999005240169935859739780426025390625
。
如果你std::cout << std::setprecision(100) << "number = " << number << std::endl;
答案 1 :(得分:1)
std :: precision设置要显示的最大有效位数
在默认浮点上 符号,精度字段 指定的最大数量 有意义的数字总计显示 计算那些之前和那些 小数点后。请注意 它不是最低限度,因此它 不填充显示的数字 如果数字可以是尾随零 显示的数字少于 精度。
30.629999999999999是30.63
的实际浮点表示答案 2 :(得分:1)
你要求十位数的精度,但实际的“不准确度”会进一步下降,所以当它被舍入到十位数时,它变得整齐30.63。你的lexical_cast会考虑所有的数字,因此产生精确的浮点值(可能不是你想要的那种精度,但它是计算机内存中最精确的表示形式)。
答案 3 :(得分:0)
问题是浮点数不能准确表示任意十进制值。您所看到的是浮点错误。 Boost准确显示您提供给它的价值。