【发布时间】:2017-01-20 10:14:52
【问题描述】:
我用 C 语言编写了一个简短的程序来执行线性插值,它通过迭代将函数的根赋予给定的小数点数。到目前为止,对于一个函数 f(x):
long double f(long double x) {
return (pow(x, 3) + 2 * x - 8);
}
程序未能收敛到 1dp 值。程序更新变量 a 和 b,f(x) 的根位于变量 a 和 b 之间,直到 a 和 b 都以给定的精度四舍五入到相同的数字。使用 long doubles 和上述函数,调试器会显示前 2 次迭代:
a = 1.5555555555555556
a = 1.6444444444444444
虽然它应该是:
a = 1.5555555555555556
a = 1.653104925053533
在此之后程序无法更新值。我使用的线性插值方程是给定here 的数学方程的重新排列版本,我使用的代码是我编写的 python 程序的 C 版本。尽管算法相同,为什么 C 实现会得到不同的值,我该如何解决?
好的,我仍然掌握了这个窍门,但希望下面我有一个最小、完整和可验证的示例:
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
long double a; long double b; long double c; // The values for interpolation
long double fofa; long double fofb; long double fofc; // The values f(a), f(b) and f(c)
const int dp = 1; // The number of decimal places to be accurate to
long double f(long double x) {
return (pow(x, 3) + 2 * x - 8);
}
int main(void) {
a = 1; b = 2;
while(roundf(a * pow(10, dp))/pow(10, dp) != roundf(b * pow(10, dp))/pow(10, dp)) { // While a and b don't round to the same number...
fofa = f(a); fofb = f(b); // Resolve the functions
printf("So f(a) = %g, f(b) = %g\n", (double)fofa, (double)fofb); // Print the results
c = (b * abs(fofa) + a * abs(fofb)) / (abs(fofb) + abs(fofa)); // Linear Interpolation
fofc = f(c);
if(fofc < 0) {
a = c;
}
else if(fofc == 0) {
a = c;
break;
}
else {
b = c;
}
}
printf("The root is %g, to %d decimal places, after %d iterations.\n", (double)a, dp, i);
}
【问题讨论】:
-
你不能使用一些调试来查看你得到的
fofa(我假设是f(a))、fofb和所有其他中间值的值吗? -
您使用什么作为
dp的值(1、10、15,其他)?当long double用于a和fofa等时,为什么还要使用float-precision 和roundf()? (你应该使用roundl()和powl()(而不是pow()),除非你使用<tgmath.h>,但是你应该提到如果你是并且你不会使用roundf()但是只是round()… -
请提供minimal reproducible example,而不是益智游戏。另见How to Ask
-
十进制数字与二进制计算的准确性有什么关系?您应该使用 epsilon 吗?我很想链接维基百科页面,但this SO question 更值得深思。
标签: c math linear-interpolation