在Matlab中求解一个由许多代数方程组成的系统

时间:2017-08-07 12:07:16

标签: matlab equations

我试图在以下形式的MATLAB中求解九个代数方程组:

eq1 = x1 * 3.12091E-17 * 10.96 * exp(x2 + x3 * 4.96) - 1765;

eq2 = x1 * 3.12091E-17 * 5.08 * exp(x2 + x3 * 5.09) - 720;

eq3 = x1 * 3.12091E-17 * 57.2 * exp(x2 + x3 * 5.22) - 7133;

eq4 = x1 * 3.12091E-17 * 1.08 * exp(x2 + x3 * 5.3) - 123;

eq5 = x1 * 3.12091E-17 * 5.01 * exp(x2 + x3 * 5.32) - 565;

eq6 = (100 - x1) * 4.91606E-18 * 0.096 * exp(x2 + x3 * 6.61) - 8;

eq7 = (100 - x1) * 4.91606E-18 * 0.318 * exp(x2 + x3 * 6.64) - 28;

eq8 = (100 - x1) * 4.91606E-18 * 0.054 * exp(x2 + x3 * 6.66) - 4;

eq9 = (100 - x1) * 4.91606E-18 * 0.832 * exp(x2 + x3 * 6.9) - 57;

该系统在九个方程中只有三个未知数。我试图使用内置的MATLAB求解器来解决它,但遗憾的是没有任何效果。未知数的正确值为:x1=4.6; x2=47; x3=-1.2

您对MATLAB无法解决此系统可能出现的错误有什么看法?

此致 I.M。

2 个答案:

答案 0 :(得分:1)

如果您在9个等式中有3个未知数,那么您的问题是overdetermined。如果你的系统有解,那么一些方程必须是其他方程的线性组合 - 简而言之,你只需要3个(线性无关)方程来求解3个变量。

接下来,正如评论中所提到的,当使用小到ActiveCell.Formula = "=IFERROR(IF(O" & ActiveCell.Row & "=""M"",LEFT(O" & ActiveCell.Row & ",LEN(O" & ActiveCell.Row & ")-1)*1000000,LEFT(O" & ActiveCell.Row & ",LEN(O" & ActiveCell.Row & ")-1)*1000000000),""" & vide & """)" 和大到10^-18的数字时,您将遇到浮点问题,尤其是在同一个表达式中!通过简单的测试,您可以看到准确度不够高

e^40

一旦你解决了这些问题,你应该看一下fsolve,这是MATLAB的非线性方程组的解算器,来自一些初步猜测。

答案 1 :(得分:0)

我认为Wolfie和Durkee在这里是错的,你只是在问题体中没有显示其他一些错误。

准确性不是问题

您将一个较大的数字乘以一个小数字。这通常不是浮点问题(除了欠/溢出情况),它的加法/减法通常会导致问题。

基本上,浮点数等于二进制的科学记数法。正如在正常的科学记数法中一样,浮点保留了相对于所用数字大小的相对准确度,因为尾数和指数是独立处理的。一个小型演示(请参阅IEEE/754 standard了解背景):

% Take two random numbers from the ENTIRE range of possible doubles: 
R  = @() typecast(randi(intmax('uint32'), 1,2, 'uint32'), 'double');
R1 = R()
R2 = R()

% Their product
p1 = R1*R2

% Compute the same product, but with randomized exponents/equal mantissas
R1 = typecast(R1,'uint64');
R2 = typecast(R2,'uint64');
for bit = 64-11:64-1 % (ignore sign bit)
    R1 = bitset(R1, bit, rand() < 0.5); 
    R2 = bitset(R2, bit, rand() < 0.5); 
end
R1 = typecast(R1,'double')
R2 = typecast(R2,'double')

p2 = R1*R2

% Show binary representations of these products
dec2bin(typecast(p1,'uint64'), 64)
dec2bin(typecast(p2,'uint64'), 64)

,例如:

R1 =
    1.455811561734462e+106
R2 =
    2.491861453769942e-128
p1 =
     3.627680714638727e-22
R1 =
    2.773851093980602e+246
R2 =
    2.835869106622333e-287
p2 =
     7.866278623790151e-41
ans =
    '0011101101111011011010001111010001111011100010001110101000000000'
ans =
    '0011011110011011011010001111010001111011100010001110101000000000'

忽略位0(符号位),这两个字符串表明只有前11位(指数)不同,但其余的(尾数)相同。这意味着p1p2都是浮点所需产品R1*R2的最佳表示形式,R1R2的大小为< em>零对精度的影响(除非/溢出下的指数)。

求解方程式

现在,回到你的问题。首先,我很好奇你是如何设法用线性系统求解器来解决一组非线性方程式的。:)

另外,当我实现你的方程式并替换你给出的值时,我得到一个负值的向量...所以我不确定你在这里解决了什么...

无论如何,我做出了合理的假设并试图用fsolve来解决你的系统问题。事实上,我发现没有实质性的问题:

function X = eqs()

    % Oh just shut up, FSOLVE...
    options = optimset('TolX'     , 1e-14,...
                       'TolFun'   , 1e-14,...
                       'Algorithm', 'Levenberg-Marquardt',...
                       'Display'  , 'off');

    % Pretend we don't know a good initial value
    done = false;
    while ~done  
        try
            [X, ~, e] = fsolve(@equations, 100*randn(3,1), options);
            done = (e==1);
        catch ME
            if ~strcmp(ME.identifier, 'optimlib:levenbergMarquardt:UsrObjUndefAtX0')
                rethrow(ME); end
        end
    end

end

function Y = equations(X)

    % Static factors
    A = 3.12091e-17 * [10.96;  5.08;  57.2;  1.08; 5.01];
    B = 4.91606e-18 * [0.096; 0.318; 0.054; 0.832];
    C = [4.96; 5.09; 5.22; 5.30; 5.32; 6.61; 6.64; 6.66; 6.90];
    D = [1765; 720; 7133; 123; 565; 8; 28; 4; 57];

    % (found by running the equation with your solution, to have a complete
    % equation compatible with fsolve)
    E = [-7.087431856800463e+02
         -3.011362826270133e+02
         -3.097892400288644e+03
         -5.378653741735363e+01
         -2.515404691148800e+02
         -3.826949873156565e+00
         -1.466555675930393e+01
         -1.789357783939141e+00
         -3.146292129042946e+01];

    % Value of the equations at current X
    Y = [A.*X(1).*ones(5,1); B.*(100-X(1)).*ones(4,1)] .* ...
        exp(X(2) + C*X(3)) - D - E;

end

结果:

>> eqs()
ans =
     4.599999930381616e+00
     4.700000001536806e+01
    -1.200000000274661e+00

这里唯一的问题可能是速度。我使用了一个非常简单的全局搜索例程:迭代地获取随机起始值,直到它们的某些组合导致fsolve收敛。在您的问题的上下文中,您可能能够进行更合理和准确的估计,从而减少计算时间。