浮点精度设置的工作原理

时间:2017-03-07 10:56:27

标签: c++ precision floating

我已经看到很多关于如何设置浮点数精度的答案以及我们在下面做的事情:

double RoundDouble(double doValue,int nPrecision)
{
    return (floor((doValue*pow(10,nPrecision)+0.5))/pow(10,nPrecision));
}

我无法理解乘法和除以几乎相等的数字会如何正确设置精度?任何人都可以详细解释

4 个答案:

答案 0 :(得分:0)

让我们一步一步来做。

  1. abstract class Vec2t<T : Number> { @JvmField var x: T @JvmField var y: T } - x = doValue * pow(10, nPrecision)数字转移到整数部分,其他数字保留在分形部分;
  2. nPrecision - 舍入到整数部分(如果y = floor(x + 0.5)为非负数);
  3. x - 将z = y / pow(10, nPrecision)位移回分形部分。

答案 1 :(得分:0)

我上面没有实现但是如果我们使用一些示例输入调试它,那么下面会发生类似的事情:

// say we have 5.89162 and we want it to 2 decimal places 5.89 so
RoundDouble(5.89162,2)
{
return (floor(5.89162*pow(10,2)+0.5))/pow(10,2);
/* which will look like
    floor((5.89162x100+0.5)/100)
     floor(589.662/100)
     floor(5.89662)
and floor function will bound it to 5 it means the output will be 5 instead of 5.89*/
}

答案 2 :(得分:0)

这只是使用整数舍入来实现我们在学校学到的用于切断一些小数位数的技巧:取小数点后的前N位数,然后向上或向下舍入最右边的数字

如果您在将12.3456四舍五入到小数点后两位时考虑到这一点,您自然会期望结果为12.35,因为'4'是两位数中最右边的数字,并且会被后面的'5'四舍五入

现在,为了通过数学实现这一点,我们利用floor来实现舍入(实际上您可以使用std::round代替)。但这将把我们带到一个整数,我们将失去所有的小数部分。

为了避免这种情况,我们首先乘以100,将所有有趣的部分移动到整数域中:

1234.56

如果您使用std::floor(x+0.5)std::round(x)将此数字四舍五入到最接近的整数值,则可获得:

1235.0

最后,将此除以100会得到四舍五入的数字(是的,请记住我们舍入它)到两位小数:

12.35

希望你现在看到调用pow时发生了什么。通过将10增加到nPrecision的幂,我们得到一个缩放因子,在使用此技巧时,在舍入后将提供许多小数位。在这种情况下,我们想要2,pow(10,2)是100。

我冒昧地清理你的功能以便于阅读:

double RoundDouble(double doValue, int nPrecision)
{
    double scale_factor = pow(10.0, static_cast<double>(nPrecision));
    return std::round(doValue * scale_factor) / scale_factor;
}

答案 3 :(得分:0)

它没有。浮点没有小数位。它有二进制位置,并且它们与小数位不相称。它所做的就是提供近似值。

有关证据,请参阅here

如果要准确地计算小数位数,则必须使用小数基数。