我已经看到很多关于如何设置浮点数精度的答案以及我们在下面做的事情:
double RoundDouble(double doValue,int nPrecision)
{
return (floor((doValue*pow(10,nPrecision)+0.5))/pow(10,nPrecision));
}
我无法理解乘法和除以几乎相等的数字会如何正确设置精度?任何人都可以详细解释
答案 0 :(得分:0)
让我们一步一步来做。
abstract class Vec2t<T : Number> {
@JvmField
var x: T
@JvmField
var y: T
}
- x = doValue * pow(10, nPrecision)
数字转移到整数部分,其他数字保留在分形部分; nPrecision
- 舍入到整数部分(如果y = floor(x + 0.5)
为非负数); 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)