【发布时间】:2014-08-21 19:17:28
【问题描述】:
我有一个介于 0 和 1 之间的浮点值。我需要将它用 -120 转换为 80。 为此,首先我在减去 120 后乘以 200。 当进行减法时,我有舍入错误。 让我们看看我的例子。
float val = 0.6050f;
val *= 200.f;
正如我所料,现在 val 是 121.0。
val -= 120.0f;
现在 val 是 0.99999992
我想也许我可以通过乘法和除法来避免这个问题。
float val = 0.6050f;
val *= 200.f;
val *= 100.f;
val -= 12000.0f;
val /= 100.f;
但这没有帮助。我手上还有 0.99。
有解决办法吗?
编辑:在详细记录之后,我知道这部分代码没有问题。在我的日志显示“0.605”之前,在我有详细的日志并且我看到“0.60499995946884155273437500000000000000000000000000”之后 问题出在不同的地方。
Edit2:我想我找到了罪魁祸首。初始值为 0.5750。
std::string floatToStr(double d)
{
std::stringstream ss;
ss << std::fixed << std::setprecision(15) << d;
return ss.str();
}
int main()
{
float val88 = 0.57500000000f;
std::cout << floatToStr(val88) << std::endl;
}
结果是 0.574999988079071
实际上,我每次都需要从这个值中加上和减去 0.0025。 通常我期望 0.575, 0.5775, 0.5800, 0.5825 ....
Edit3:实际上我用双倍尝试了所有这些。它适用于我的示例。
std::string doubleToStr(double d)
{
std::stringstream ss;
ss << std::fixed << std::setprecision(15) << d;
return ss.str();
}
int main()
{
double val88 = 0.575;
std::cout << doubleToStr(val88) << std::endl;
val88 += 0.0025;
std::cout << doubleToStr(val88) << std::endl;
val88 += 0.0025;
std::cout << doubleToStr(val88) << std::endl;
val88 += 0.0025;
std::cout << doubleToStr(val88) << std::endl;
return 0;
}
结果是:
0.575000000000000
0.577500000000000
0.580000000000000
0.582500000000000
但不幸的是,我一定会漂浮。我需要改变很多东西。
感谢大家的帮助。
Edit4:我找到了我的字符串解决方案。我使用 ostringstream 的舍入并在此之后转换为双精度。我可以有 4 个精确的正确数字。
std::string doubleToStr(double d, int precision)
{
std::stringstream ss;
ss << std::fixed << std::setprecision(precision) << d;
return ss.str();
}
double val945 = (double)0.575f;
std::cout << doubleToStr(val945, 4) << std::endl;
std::cout << doubleToStr(val945, 15) << std::endl;
std::cout << atof(doubleToStr(val945, 4).c_str()) << std::endl;
结果是:
0.5750
0.574999988079071
0.575
【问题讨论】:
-
太糟糕了,它是浮点数。总会有不准确的地方。
-
0.6050.f是语法错误。我想你的意思是0.6050f。请复制并粘贴确切的代码。 -
我无法重现您的结果。那不是你真正的代码,是吗?
-
另外两美分,解决这个问题的唯一方法是不使用浮点数。根据定义,浮点数是近似值,但您正在查看的数字范围都可以存储在 32 位定点数中。
标签: c++ floating-point