- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在制作一个简单的函数来重现 Secant method ,我认为我在精度方面遇到了一些问题。
首先,这是函数(以及调用它的主要方法,以及与之一起使用的测试函数):
double secant_method(double(*f)(double), double a, double b){
double c;
for (int i = 0; i < 10; i++){
c = a - f(a) * (a - b) / (f(a) - f(b));
b = a; a = c;
}
return c;
}
typedef double (*func)(double);
//test function - x^3 + 4x - 10
double test(double x){
return (x*x*x) + (4*x) - 10;
}
int main(){
func f = &test;
double ans;
ans = secant_method(f, 0, 2);
printf("\nRoot found:\t%.*g\n", DECIMAL_DIG * 2, ans);
return 0;
}
注意:for
在函数中循环 secant_method()
只循环10次。这就是我的问题所在。
按原样打印时,一切正常。它给出了小数点后 16 位的正确输出:
但是,当我向 for
添加迭代时循环 secant_method()
,这发生了:
为什么会这样?我是否达到了 C 可以处理的最大表示?
我通读了this great answer来自另一篇文章,但在其中,关于我收到的异常 ( -1.#IND
),它只是说我的结果不是数字,或者我正在进行某种非法操作。
编辑使用(x*x*x) + (4*x) - 10 + sin(x)
因为我的测试函数给出了正确的答案——但前提是我在 i < 9
时循环, 而不是 i < 10
对于 (x*x*x) + (4*x) - 10
最佳答案
-1.#IND
是 Microsoft 输出不确定值的方式,特别是 NaN
.
一种这可能发生的方式是 0 / 0
但我会检查所有操作以查看问题所在:
double secant_method(double(*f)(double), double a, double b){
double c;
printf("DBG =====\n");
for (int i = 0; i < 10; i++){
printf("\nDBG -----\n");
printf("DBG i: %d\n",i);
printf("DBG a: %30f\n",a);
printf("DBG b: %30f\n",b);
printf("DBG c: %30f\n",c);
printf("DBG f(a): %30f\n",f(a));
printf("DBG a-b: %30f\n",a-b);
printf("DBG f(b): %30f\n",f(b));
printf("DBG f(a)-f(b): %30f\n",f(a)-f(b));
printf("DBG f(a)*(a-b): %30f\n",f(a)*(a-b));
printf("DBG f(a)*(a-b)/(f(a)-f(b)): %30f\n",f(a)*(a-b)/(f(a)-f(b)));
c = a - f(a) * (a - b) / (f(a) - f(b));
b = a; a = c;
}
return c;
}
一旦您获得了调试输出,然后您就可以弄清楚实际问题是什么,并采取策略来避免它。
当我这样做时,我看到(最后):
DBG -----
DBG i: 8
DBG a: 1.556773264394211375716281509085
DBG b: 1.556773264393484179635152031551
DBG c: 1.556773264394211375716281509085
DBG f(a): -0.000000000000000987057657830803
DBG a-b: 0.000000000000727196081129477534
DBG f(b): -0.000000000008196943991622962500
DBG f(a)-f(b): 0.000000000008195956933965131697
DBG f(a)*(a-b): -0.000000000000000000000000000718
DBG f(a)*(a-b)/(f(a)-f(b)): -0.000000000000000087577871187781
DBG -----
DBG i: 9
DBG a: 1.556773264394211375716281509085
DBG b: 1.556773264394211375716281509085
DBG c: 1.556773264394211375716281509085
DBG f(a): -0.000000000000000987057657830803
DBG a-b: 0.000000000000000000000000000000
DBG f(b): -0.000000000000000987057657830803
DBG f(a)-f(b): 0.000000000000000000000000000000
DBG f(a)*(a-b): -0.000000000000000000000000000000
DBG f(a)*(a-b)/(f(a)-f(b)): nan
Root found: nan
所以你可以看到,在第十次迭代中,a
和 b
变得平等,因此也是f(a)
和 f(b)
.所以你得到了表达式:
something * 0 / 0
如前所述,它会给你 0 / 0
或 NaN
.
就如何修复它而言,您只需要避免除以零,因为这会给您一个 NaN
或无穷大。因此,您可以改用以下函数:
double secant_method(double(*f)(double), double a, double b){
double c;
for (int i = 0; i < 1000; i++) {
if (f(a) == f(b)) break;
c = a - f(a) * (a - b) / (f(a) - f(b));
b = a; a = c;
}
return c;
}
一千个循环应该足以得到一个像样的答案,如果你要除以零,它会提前退出。
如果您想要更多 精度,您可以查看 long double
键入或切换到使用任意精度算术库之一,例如 GMP 或 MPIR。
这通常需要更多的工作,但您可以获得一些令人印象深刻的结果。这个基于 MPIR 的程序:
#include <stdio.h>
#include <mpir.h>
void secant_method(mpf_t result, void(*f)(mpf_t, mpf_t), mpf_t a, mpf_t b){
mpf_t c, fa, fb, temp1, temp2;
mpf_init (fa);
mpf_init (fb);
mpf_init (temp1);
mpf_init (temp2);
for (int i = 0; i < 1000; i++){
printf("DBG i: %d\n",i);
f (fa, a);
f (fb, b);
if (mpf_cmp (fa, fb) == 0) break;
mpf_set (temp1, a);
mpf_sub (temp1, temp1, b);
mpf_set (temp2, fa);
mpf_sub (temp2, temp2, fb);
mpf_set (result, fa);
mpf_mul (result, result, temp1);
mpf_div (result, result, temp2);
mpf_sub (result, result, a);
mpf_neg (result, result);
mpf_set (b, a);
mpf_set (a, result);
}
}
void test (mpf_t result, mpf_t x){
mpf_t temp;
mpf_set (result, x);
mpf_pow_ui (result, result, 3);
mpf_init_set (temp, x);
mpf_mul_ui (temp, temp, 4);
mpf_add (result, result, temp);
mpf_set_ui (temp, 10);
mpf_sub (result, result, temp);
mpf_clear (temp);
}
int main(){
mpf_t ans, a, b;
mpf_set_default_prec (8000);
mpf_init_set_ui (ans, 0);
mpf_init_set_ui (a, 0);
mpf_init_set_ui (b, 2);
secant_method (ans, &test, a, b);
mpf_out_str (stdout, 10, 0, ans);
return 0;
}
输出精度更高,大约二位半千位:
DBG i: 1
:
DBG i: 19
0.155677326439421146326886324730853302634853266143
22856485101283627988036767055520913212330822780959
93349183787687346999781239000417393618333668026011
02048595843228945228507966189601958673920851932189
20626590635658264390975889008832048255537650792123
54916373054888140164770654992918100928227714960414
65208113116379497717707745267800989233875981344305
90022883167106124203999713536673991376957068731244
91919087980169395013246250812213656324598765244218
15974098310512802880727074335472786858740154287363
31949470951650710072488856623955478366217474755111
76368234254761541647442609230138418167182918204711
66713459423756284737546964906061587903876515793884
14091165347411853670752820576131460960421137744435
73729141652832258144582021037373967987171478026002
48487515446248979731517957120705447608265161099693
33098235693813752370774508652788986557620510981156
19907950657355934071535840759135251701581523712307
00051674680667972152582339710574822560693109306285
91240827697915787078746087225027856691436076089912
35551789799825731841345891629028445554314717823386
07885164744100235567602875364878328805811271289098
87558119684442289199181352023304600847178256323082
57317198584882656089836229208443415369358460418542
84083408696290686178971039756668669303212658278679
39542421457300944206839268283788585029652481323614
65995074020560963212330914882733926627309382310653
39023265929195094492468196461296569155421718696631
73798097369621805062145075113127308161572398104766
37356504104570136778437926442139603916930640425421
15655156674699552536588332891562053247342008145504
44336211031437923307615880759201695011419324719812
46482293928341901673056596202744639074280785106031
90197472588293352508389295101867514582271001202777
85575614897203080940643669476500979934666490279524
88486176409290187337498631681392563044899541391612
88438904336237873504970887963071622208868799638373
42186338496601471274609131141920820263780493617795
89714798662834913192777810386631915415021934333441
01797098172897161215116673422762953435902633516501
73788202968876596925999628999004575114529754782488
59959395407324243559011982543407738505315960009874
36510513519775603567237051670918870105777288994910
85524037720122749091827520695838000086150188462000
63190624219373460624686216781527327604063990319908
56547016812115842640285111265677758613385414834511
69237199199725030839166586376374587900611430229333
87296847315023767826706323911923435564643861604120
017381909481e1
并且,如果您获取该数字并将其传递回 test()
函数,你得到一个相当接近于零的数字,大约 -1.15 x 10<sup>-2408</sup>
.所以我想说这是对使用 double
的一个相当大的改进。 .
而且,就其值(value)而言,它只需要大约十分之一秒的 CPU 时间,因此至少用任意精度的算法来做到这一点是可行的。
要获得更的精度,只需更改 MPIR 的默认精度设置,当前设置为:
mpf_set_default_prec (8000);
增加到 100,000 会给出超过 30,000 位有效数字的答案,最终“接近于零”的答案约为 -5 x 10<sup>-30103</sup>
。 .
关于c - IEEE 浮点异常 - 为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28713865/
这个问题已经有答案了: Invalid types 'double [100][double]' for array subscript (3 个回答) 已关闭 6 年前。 我已复制下面的整个代码并在
您有 2 个功能; f(x)= x(((x+1)^(1/2))-(x^(1/2))) g(x)= x/(((x+1)^(1/2))+(x^(1/2))) 哪个更准确? 旁注:如果你能解释为什么,
我正在从事一个关于java的研究项目,其中必须完成一些艰难的计算。然而,我已经完成了大部分工作,但停留在某个点上。我必须计算以下内容: (2.1-2.3) raised to power 0.3. 但
int main() { float x = 50; float y = 1/x; float result = y * x; float test = 41;
有没有安全的方法来可靠地确定整数类型 T可以存储浮点整数值 f (所以 f == floor(f) )没有任何溢出? 请记住,不能保证浮点类型 F与 IEC 559 (IEEE 754) 兼容,并且有
// value will always be in the range of [0.0 - maximum] float obtainRatio(float value, float maximum
就在今天,我遇到了我们正在使用的第三方软件,在他们的示例代码中,有以下内容: // Defined in somewhere.h static const double BAR = 3.14; //
是否有推荐的方法来清除 jQuery Flot 图表?我在 API 引用中找不到任何内容。 最佳答案 “清除”是指“破坏整个图表”还是只是清除数据? 要核对整个图表:$('#canvas_id').e
我正在学习单精度并想了解错误传播。根据this nice website ,加法是一个危险的操作。 所以我编写了一个小的 C 程序来测试错误累积的速度。我不完全确定这是否是一种有效的测试方法。如果是,
我正在尝试查询数据库,我需要获取权重等于 60.5 的客户列表。问题是 60.5 是一个实数,我以前从未在 where 子句中使用实数查询过数据库。 我已经尝试过这个: SELECT Name FRO
这是我的“ProjectEntity”类中的代码部分(我在其中使用 hibernate 进行 SQL 调用) @Column(name = "BUDGET") private float budget
我用 Haskell 编写了一个应用程序,它调用 Z3 求解器来解决一些复杂公式的约束。感谢 Haskell,我可以快速切换正在使用的数据类型。 当使用 SBV 的 AlgReal 类型进行计算时,我
在 C 中 double/float 有一个集合类型说明符:%f %F %g %G %e %E .有什么区别吗 %f和 %F , %g和 %G , %e和 %E ? 根据 printf和 scanf输
我正在开发一个适用于 Android 的可视化应用程序(包括运行 Android 2.2 的旧设备)。 我的应用程序的输入模型包含一个区域,该区域通常由数万个顶点组成。典型模型有 50000-1000
关闭。这个问题需要多问focused 。目前不接受答案。 想要改进此问题吗?更新问题,使其仅关注一个问题 editing this post . 已关闭 6 年前。 Improve this ques
我被要求编写一个程序来查找我大学中两个输入的总和,因此我应该首先检查输入是否有效。 例如,如果我输入 2534.11s35,程序应该检测到它不是该程序的有效输入,因为输入中存在 s。 最佳答案 to
我正在尝试降低 FPGA 的逻辑利用率,但在网上找不到任何好的 float fastpow。我所说的“好”是指充分减少所使用的逻辑。如果我使用双版本我几乎没有什么改进。如果我使用其他依赖日志的 flo
我有一个 128 字节的内存位置。我尝试用从 1...127 开始的数据填充内存。 我需要编写一个代码来获取两个参数,如偏移量、数据类型。根据参数,我需要将内存中的数据转换为提到的特定数据类型。 举个
我希望能够做到以下几点: float func() { if( error ) return InvalidFloatingPointValue; else return 0.0f;
假设我有两个 float ,我想比较它们。如果一个大于另一个,程序应该采用一个 fork。如果情况正好相反,它应该走另一条路。并且它应该做同样的事情,如果被比较的值在一个仍然应该使它比较真实的方向上被
我是一名优秀的程序员,十分优秀!