在我的程序中,某些双精度数具有一些精度(一些正整数,在大多数情况下应为形式),因此double * precision
应该成为整数。
但是众所周知,浮点数是不准确的,因此,例如1.3029515
可以另存为1.3029514999999998...
,在我的程序中,我需要将这种浮点数写入文件,但是我希望将此1.3029515
转换为文件。而不是像1.3029514999999998...
这样的文字。
以前,我的程序只使用形式精度,而我通过下面的代码达到了想要的结果:
// I have a function for doubles equality check
inline bool sameDoubles(const double& lhs, const double& rhs, const double& epsilon) {
return fabs(lhs - rhs) < epsilon;
}
inline void roundDownDouble(double& value, const unsigned int& numberOfDigitsInFraction = 6) {
assert(numberOfDigitsInFraction <= 9);
double factor = pow(10.0, numberOfDigitsInFraction);
double oldValue = value;
value = (((int)(value * factor)) / factor);
// when, for example, 1.45 is stored as 1.4499999999..., we can get wrong value, so, need to do the check below
double diff = pow(10.0, 0.0 - numberOfDigitsInFraction);
if(sameDoubles(diff, fabs(oldValue - value), 1e-9)) {
value += diff;
}
};
但是现在,我无法使用相同的技术来获得所需的结果,我尝试了以下功能,但未成功:
// calculates logarithm of number with given base
double inline logNbase(double number, double base) {
return log(number)/log(base);
}
// sameDoubles function is the same as in above case
inline void roundDownDouble(double& value, unsigned int precision = 1e+6) {
if(sameDoubles(value, 0.0)) { value = 0; return; }
double oldValue = value;
value = ((long int)(value * precision) / (double)precision);
// when, for example, 1.45 is stored as 1.4499999999..., we can get wrong value, so, need to do the check below
int pwr = (int)(logNbase((double)precision, 10.0));
long int coeff = precision / pow(10, pwr);
double diff = coeff * pow(10, -pwr);
if(sameDoubles(diff, fabs(oldValue - value), diff / 10.0)) {
if(value > 0.0) {
value += diff;
} else {
value -= diff;
}
}
}
对于
1.3029515
值和precision = 2000000
,此函数返回不正确的1.302951
值(表达式(long int)(value * precision)
等于2605902
而不是2605903
)。我怎样才能解决这个问题?也许有一些聪明的方法可以使舍入正确进行?
最佳答案
您正在艰难地四舍五入。改为使用简单的方法:
double rounding = 0.5;
if (value < 0.0) rounding = -0.5;
value = ((long int)(value * precision + rounding) / (double)precision);
现在,无需其余代码。