简体   繁体   English

求解 Matlab 一个系数很小的二次方程

[英]solve In Matlab a quadratic equation with very small coefficients

I'm implementing a code in matlab to solve quadratic equations, using the resolvent formula:我正在 matlab 中实现一个代码来求解二次方程,使用分解公式:

在此处输入图像描述

Here´s the code:这是代码:

clear all 
format short 
a=1; b=30000000.001; c=1/4; 
rdelta=sqrt(b^2-4*a*c); 
x1=(-b+rdelta)/(2*a);
x2=(-b-rdelta)/(2*a);
fprintf(' Roots of the polynomial %5.3f x^2 + %5.3f x+%5.3f \n',a,b,c)  
fprintf ('x1= %e\n',x1)
fprintf ('x2= %e\n\n',x2)
valor_real_x1= -8.3333e-009;
valor_real_x2= -2.6844e+007;

error_abs_x1 = abs (valor_real_x1-x1);
error_abs_x2 = abs (valor_real_x2-x2);

error_rel_x1 = abs (error_abs_x1/valor_real_x1);
error_rel_x2 = abs (error_abs_x2/valor_real_x2);

fprintf(' absolute_errorx1 = |real value - obtained value| = |%e - %e| = %e \n',valor_real_x1,x1,error_abs_x1)  
fprintf(' absolute_errorx2 = |real value - obtained value| = |%e - %e| = %e \n\n',valor_real_x2,x2,error_abs_x2) 

fprintf(' relative error_x1 = |absolut error / real value| = |%e / %e| = %e \n',error_abs_x1,valor_real_x1,error_rel_x1 ) 
 fprintf(' relative_error_x2 = |absolut error / real value|  = |%e / %e| = %e \n',error_abs_x2,valor_real_x2,error_rel_x2) 

The problem I have is that it gives me an exact solution, ie for values a = 1, b = 30000000,001 c = 1/4, the values of the roots are:我遇到的问题是它给了我一个精确的解决方案,即对于值 a = 1,b = 30000000,001 c = 1/4,根的值为:

Roots of the polynomial 1.000 x^2 + 30000000.001 x+0.250 
 x1= -9.313226e-009
 x2= -3.000000e+007

Knowing that the exact value of the roots of the polynomial are:知道多项式的根的确切值为:

x1= -8.3333e-009
x2= -2.6844e+007

Which gives me the following errors in the absolute and relative precision of the calculations:这让我在计算的绝对和相对精度方面出现以下错误:

 absolute_errorx1 = |real value - obtained value| = |-8.333300e-009 - -9.313226e-009| = 9.799257e-010 
 absolute_errorx2 = |real value - obtained value| = |-2.684400e+007 - -3.000000e+007| = 3.156000e+006 

 relative error_x1 = |absolut error / real value| = |9.799257e-010 / -8.333300e-009| = 1.175916e-001 
 relative_error_x2 = |absolut error / real value|  = |3.156000e+006 / -2.684400e+007| = 1.175682e-001

My question is: Is there an optimum method to obtain the roots of a quadratic equation?, ie I can make changes to my code to reduce the relative error between the expected solution and the resulting solution?我的问题是:是否有获得二次方程根的最佳方法?即我可以更改我的代码以减少预期解与结果解之间的相对误差吗?

Using the quadratic formula directly in this cases results in a large loss of numerical precision from subtracting two values of very similar magnitude.在这种情况下直接使用二次公式会导致减去两个幅度非常相似的值而导致数值精度大幅下降。 This is because the expression这是因为表达式

sqrt(b*b - 4*a*c)

is nearly the same as b.与 b 几乎相同。 So you should use only one of these two roots, the one that does not involve subtracting two very close values, and for the other root you can use (for instance) the fact that the product of roots of a quadratic is c/a.所以你应该只使用这两个根中的一个,一个不涉及减去两个非常接近的值的根,而对于另一个根你可以使用(例如)二次根的乘积是 c/a 这一事实。 I'll let you fill in the gaps.我会让你填补空白。

Why does this sound like a homework problem from a first class in numerical analysis?为什么这听起来像是数值分析中第一个 class 的家庭作业问题?

It has been a while since I was that young, but as I recall there is a trick.自从我那么年轻以来已经有一段时间了,但我记得有一个窍门。 Anyway, you are wrong.不管怎样,你错了。 The true roots of that polynomial are该多项式的真根是

solve('x^2 + 30000000.001*x + 0.25')
ans =
          -30000000.000999991666666666944442
 -0.0000000083333333330555578703796293981491

How well does roots do here?根在这里的表现如何?

p = [1 30000000.001 1/4];
format long g
roots(p)
ans =
             -30000000.001
     -8.33333333305556e-09

That actually seems pretty good.这实际上看起来很不错。 How does HPF do? HPF 是怎么做的?

DefaultNumberOfDigits 64
a = hpf(1);
b = hpf('30000000.001');
c = hpf('0.25');

r1 = (-b + sqrt(b*b - 4*a*c))/(2*a)
r1 =
-0.000000008333333333055557870379629398149125529835186899898569329967

r2 = (-b - sqrt(b*b - 4*a*c))/(2*a)
r2 =
-30000000.000999991666666666944442129620370601850874470164813100101

Yep, HPF works nicely enough too.是的,HPF 也能很好地工作。

So what happens when you use double precision numbers and the standard formula?那么当您使用双精度数字和标准公式时会发生什么? Yeah, crapola arrives.是的,crapola 来了。

a = 1;
b = 30000000.001;
c = 0.25;

>> r1 = (-b + sqrt(b*b - 4*a*c))/(2*a)
r1 =
     -7.45058059692383e-09

>> r2 = (-b - sqrt(b*b - 4*a*c))/(2*a)
r2 =
             -30000000.001

Again, massive subtractive cancellation eats away at the result.同样,大量的减法抵消会侵蚀结果。 (I seem to recall that was the problem you had in your last question.) (我似乎记得那是你在上一个问题中遇到的问题。)

There is a trick you can use.您可以使用一个技巧。 See that the large solution was well estimated, just not the one near zero.看到大的解决方案得到了很好的估计,而不是接近零的那个。 So, what happens if you solved for the roots of fliplr(p) using the quadratic formula?那么,如果您使用二次公式求解 fliplr(p) 的根会怎样? How does this solve your problem?这如何解决您的问题? What transformation is implicitly done when you do that?当你这样做时,隐含地做了什么转换? (Sorry, but I won't do your homework. I think the above was enough of a hint anyway.) (对不起,但我不会做你的功课。我认为上面的提示已经足够了。)

i think your "real" values might be wrong (or maybe it's a precision thing... I dunno)我认为你的“真实”价值观可能是错误的(或者这可能是一个精确的事情......我不知道)

a*(valor_real_x1^2)+b*(valor_real_x1)+c

ans =

   9.9999e-07

a*(valor_real_x2^2)+b*(valor_real_x2)+c

ans =

  -8.4720e+13

A nice formula for this problem:这个问题的一个很好的公式:

var q = sqrt(c*a)/b;
var f = .5 + .5 *sqrt(1-4*q*q);
var x1=-b*f/a;
var x2=-c/(f*b);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM