gpt4 book ai didi

c++ - 避免双数舍入

转载 作者:行者123 更新时间:2023-11-28 01:50:35 24 4
gpt4 key购买 nike

我正在尝试编写一个函数,使用最小二乘法从数据表中计算回归线,但我的代码遇到了一些严重的问题。

我的第一个问题是我不知道为什么我的“线性回归”函数会四舍五入迭代的结果,即使我正在尝试使用其他“更大”的类型也是如此。

我的第二个问题是我代码的最后一部分给出了错误的 y 截距 (b) 和斜率 (a) 结果,我认为这可能是转换问题,但我不是非常肯定。如果是这种情况,我应该怎么做才能避免它?

void RegLin (const vector<double>& valuesX, const vector<double>& valuesY, vector<double>& PenOrd) {

unsigned int N=valuesX.size();

long double SomXi{0};
for (unsigned i=0; i<N; ++i){
SomXi+=valuesX.at(i);
}

long double SomXiXi{0};
for (unsigned i=0; i<N; ++i){ //Here is a problem (number rounded) Expected value: 937352,25 / Given value: 937352
SomXiXi+=(valuesX.at(i))*(valuesX.at(i));
}

long double SomYi{0};
for (unsigned i=0; i<N; ++i){
SomYi+=valuesY.at(i);
}

long double SomXiYi{0};
for (unsigned i=0; i<N; ++i){ //Here is the same problem Excepted value: 334107,41 / Given value: 334107
SomXiYi+=(valuesX.at(i))*(valuesY.at(i));
}

long double a=(SomYi*SomXiXi-SomXi*SomXiYi)/(N*SomXiXi-pow(SomXi,2)); //Bad result

long double b=(N*SomXiYi-SomYi*SomXi)/(N*SomXiXi-pow(SomXi,2)); //Bad result

PenOrd.push_back(a);
PenOrd.push_back(b);

return;
}

提前感谢您的支持

P.S:我使用的是 g++ 和 2011 C++ 标准。

最佳答案

你的努力有几个点。我是一名理论物理学和数值数学专家。因此,让我与您分享一些最佳实践。

首先,我从未遇到过使用long double 的需要。坚持使用 double,因为如果这还不够,那么您应该考虑使用对数-对数图来进一步分析您的数据。

其次,您正在使用unsigned int 而不是int。您永远不应该使用太多的值(即值对)进行回归工作,以至于对整数计数器使用 int 或最佳 std::size_t 是不够的.由于累积的数值舍入问题,使用太多值会降低准确性。因此,除非您有充分的理由这样做,否则不要使用超过 10000 到 100 万的值。

第三,很快就有必要不要直截了本地加上你的方 block (例如,对于 SumXiXi 等等),而是在实际求和之前对你对总和的贡献进行排序。你正确地总结了它们,从最微小的值(value)开始,随着你对总和的贡献不断增加。这是解决不断累积的舍入问题的唯一方法。

第四,结果的控制。结果可靠性的一个好迹象是可以实现的,如果你两次工作,一次是你所做的(即使用 x_iy_i - xy_i - x_iy + xy 公式)然后作为第二种方法使用仍未乘法的 (x_i - x)(y_i - y) 公式。高质量的计算将使用任一公式产生非常可比的结果。

所以,也许在进行数值回归工作时走了很多弯路,希望它能有所帮助。

问候,米夏

关于c++ - 避免双数舍入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43169944/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com