这是物理引擎的一部分
简化函数centerOfMass
计算两个刚体(demo)的1D-质心: -
#include <iostream>
#include <iomanip>
float centerOfMass(float pos1,float m1, float pos2,float m2){
return (pos1*m1+pos2*m2)/(m1+m2);
}
int main(){
float a=5.55709743f;
float b= centerOfMass(a,50,0,0);
std::cout << std::setprecision(9) << a << '\n'; //5.55709743
std::cout << std::setprecision(9) << b << '\n'; //5.55709696
}
我需要b
精确= 5.55709743。
微小的差异,有时(我的真实情况= 5%),会引入令人讨厌的物理分歧 有一些方法可以解决它,例如大力做一些有条件的检查 但是,这对我来说非常容易出错。
问题:如何在保持代码干净,快速且易于维护的同时解决计算错误?
顺便说一句,如果不能优雅地完成,我可能需要改进调用者以更好地抵抗这种数字错误。
(澄清重复的问题)
是的,原因是存储/计算格式的精确错误(在Is floating point math broken?中提到)。
但是,此问题询问如何在非常具体的情况下 中和 其症状。
答案 0 :(得分:2)
您正在尝试获得9个十进制数字的精度,但数据类型float
具有precision of about 7 decimal digits。
使用double
代替。 (demo)
答案 1 :(得分:1)
使用double,而不是float。 IEEE 754 double有大约16位小数的精度。
#include <iostream>
#include <iomanip>
double centerOfMass(double pos1, double m1, double pos2, double m2) {
return (pos1*m1 + pos2 * m2) / (m1 + m2);
}
int main() {
double a = 5.55709743;
double b = centerOfMass(a, 50, 0, 0);
std::cout << std::setprecision(16) << a << '\n'; //5.55709743
std::cout << std::setprecision(16) << b << '\n'; //5.55709743
std::cout << std::setprecision(16) << (b - a) << '\n'; // 0
}
对于给定的示例,centerOfMass(a,50,0,0),以下内容将给出a的所有值的精确结果,但当然示例看起来并不现实。
double centerOfMass(double pos1, double m1, double pos2, double m2) {
double divisor = m1 + m2;
return pos1*(m1/divisor) + pos2*(m2/ divisor);
}