最小二乘法–高斯牛顿迭代法

时间:2023-01-07 22:59:26

最小二乘法–高斯牛顿迭代法

本文将详解最小二乘法的非线性拟合,高斯牛顿迭代法。

1.原理

高斯—牛顿迭代法的基本思想是使用泰勒级数展开式去近似地代替非线性回归模型,然后通过多次迭代,多次修正回归系数,使回归系数不断逼近非线性回归模型的最佳回归系数,最后使原模型的残差平方和达到最小。

①已知m个点:

最小二乘法–高斯牛顿迭代法

②函数原型:

最小二乘法–高斯牛顿迭代法

其中:(m>=n)

最小二乘法–高斯牛顿迭代法

③目的是找到最优解β,使得残差平方和最小:

最小二乘法–高斯牛顿迭代法

残差:

最小二乘法–高斯牛顿迭代法

④要求最小值,即S的对β偏导数等于0:

最小二乘法–高斯牛顿迭代法

⑤在非线性系统中,最小二乘法–高斯牛顿迭代法是变量和参数的函数,没有close解。因此,我们给定一个初始值,用迭代法逼近解:

最小二乘法–高斯牛顿迭代法

其中k是迭代次数,最小二乘法–高斯牛顿迭代法是迭代矢量。

⑥而每次迭代函数是线性的,在最小二乘法–高斯牛顿迭代法处用泰勒级数展开:

最小二乘法–高斯牛顿迭代法

其中:J是已知的矩阵,为了方便迭代,令最小二乘法–高斯牛顿迭代法

⑦此时残差表示为:

最小二乘法–高斯牛顿迭代法

最小二乘法–高斯牛顿迭代法

⑧带入公式④有:

最小二乘法–高斯牛顿迭代法

化解得:

最小二乘法–高斯牛顿迭代法

⑨写成矩阵形式:

最小二乘法–高斯牛顿迭代法

⑩所以最终迭代公式为:

最小二乘法–高斯牛顿迭代法

其中,Jf是函数f=(x,β)对β的雅可比矩阵。

2.代码

Java代码实现,解*的例子:

https://en.wikipedia.org/wiki/Gauss%E2%80%93Newton_algorithm

①已知数据:

最小二乘法–高斯牛顿迭代法

②函数模型:

最小二乘法–高斯牛顿迭代法

③残差公式:

最小二乘法–高斯牛顿迭代法

④对β求偏导数:

最小二乘法–高斯牛顿迭代法

⑤代码如下:

<code class="hljs cs has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> GaussNewton {
<span class="hljs-keyword">double</span>[] xData = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[]{<span class="hljs-number">0.038</span>, <span class="hljs-number">0.194</span>, <span class="hljs-number">0.425</span>, <span class="hljs-number">0.626</span>, <span class="hljs-number">1.253</span>, <span class="hljs-number">2.500</span>, <span class="hljs-number">3.740</span>};
<span class="hljs-keyword">double</span>[] yData = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[]{<span class="hljs-number">0.050</span>, <span class="hljs-number">0.127</span>, <span class="hljs-number">0.094</span>, <span class="hljs-number">0.2122</span>, <span class="hljs-number">0.2729</span>, <span class="hljs-number">0.2665</span>, <span class="hljs-number">0.3317</span>};

<span class="hljs-keyword">double</span>[][] bMatrix = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[<span class="hljs-number">2</span>][<span class="hljs-number">1</span>];<span class="hljs-comment">//系数β矩阵</span>
<span class="hljs-keyword">int</span> m = xData.length;
<span class="hljs-keyword">int</span> n = bMatrix.length;
<span class="hljs-keyword">int</span> iterations = <span class="hljs-number">7</span>;<span class="hljs-comment">//迭代次数</span>

<span class="hljs-comment">//迭代公式求解,即1中公式⑩</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">magic</span>(){
<span class="hljs-comment">//β1,β2迭代初值</span>
bMatrix[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>] = <span class="hljs-number">0.9</span>;
bMatrix[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>] = <span class="hljs-number">0.2</span>;

<span class="hljs-comment">//求J矩阵</span>
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> k = <span class="hljs-number">0</span>; k < iterations; k++) {
<span class="hljs-keyword">double</span>[][] J = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[m][n];
<span class="hljs-keyword">double</span>[][] JT = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[n][m];
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < m; i++){
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j < n; j++) {
J[i][j] = secondDerivative(xData[i], bMatrix[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>], bMatrix[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>], j);
}
}

JT = MatrixMath.invert(J);<span class="hljs-comment">//求转置矩阵JT</span>
<span class="hljs-keyword">double</span>[][] invertedPart = MatrixMath.mult(JT, J);<span class="hljs-comment">//矩阵JT与J相乘</span>

<span class="hljs-comment">//矩阵invertedPart行列式的值:|JT*J|</span>
<span class="hljs-keyword">double</span> result = MatrixMath.mathDeterminantCalculation(invertedPart);

<span class="hljs-comment">//求矩阵invertedPart的逆矩阵:(JT*J)^-1</span>
<span class="hljs-keyword">double</span>[][] reversedPart = MatrixMath.getInverseMatrix(invertedPart, result);

<span class="hljs-comment">//求方差r(β)矩阵: ri = yi - f(xi, b)</span>
<span class="hljs-keyword">double</span>[][] residuals = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[m][<span class="hljs-number">1</span>];
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < m; i++) {
residuals[i][<span class="hljs-number">0</span>] = yData[i] - (bMatrix[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>] * xData[i]) / (bMatrix[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>] + xData[i]);
}

<span class="hljs-comment">//求矩阵积reversedPart*JT*residuals: (JT*J)^-1*JT*r</span>
<span class="hljs-keyword">double</span>[][] product = MatrixMath.mult(MatrixMath.mult(reversedPart, JT), residuals);

<span class="hljs-comment">//迭代公式, 即公式⑩</span>
<span class="hljs-keyword">double</span>[][] newB = MatrixMath.plus(bMatrix, product);
bMatrix = newB;
}
<span class="hljs-comment">//显示系数值</span>
System.<span class="hljs-keyword">out</span>.println(<span class="hljs-string">"b1: "</span> + bMatrix[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>] + <span class="hljs-string">"\nb2: "</span> + bMatrix[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>]);
}

<span class="hljs-comment">//2中公式④</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span> <span class="hljs-title">secondDerivative</span>(<span class="hljs-keyword">double</span> x, <span class="hljs-keyword">double</span> b1, <span class="hljs-keyword">double</span> b2, <span class="hljs-keyword">int</span> index){
<span class="hljs-keyword">switch</span>(index) {
<span class="hljs-keyword">case</span> <span class="hljs-number">0</span>: <span class="hljs-keyword">return</span> x / (b2 + x);<span class="hljs-comment">//对系数bi求导</span>
<span class="hljs-keyword">case</span> <span class="hljs-number">1</span>: <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span> * (b1 * x) / Math.pow((b2+x), <span class="hljs-number">2</span>);<span class="hljs-comment">//对系数b2求导</span>
}
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String[] args) {
GaussNewton app = <span class="hljs-keyword">new</span> GaussNewton();
app.magic();
}
}</code><ul class="pre-numbering" style="opacity: 0.454786;"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li></ul><div class="save_code tracking-ad" style="display: none;" data-mod="popu_249"><a target=_blank target="_blank"><img src="http://static.blog.csdn.net/images/save_snippets.png" alt="" /></a></div><ul class="pre-numbering"><li>1</li><li>2</li><li>3</li><li>4</li><li>5</li><li>6</li><li>7</li><li>8</li><li>9</li><li>10</li><li>11</li><li>12</li><li>13</li><li>14</li><li>15</li><li>16</li><li>17</li><li>18</li><li>19</li><li>20</li><li>21</li><li>22</li><li>23</li><li>24</li><li>25</li><li>26</li><li>27</li><li>28</li><li>29</li><li>30</li><li>31</li><li>32</li><li>33</li><li>34</li><li>35</li><li>36</li><li>37</li><li>38</li><li>39</li><li>40</li><li>41</li><li>42</li><li>43</li><li>44</li><li>45</li><li>46</li><li>47</li><li>48</li><li>49</li><li>50</li><li>51</li><li>52</li><li>53</li><li>54</li><li>55</li><li>56</li><li>57</li><li>58</li><li>59</li><li>60</li><li>61</li><li>62</li><li>63</li><li>64</li><li>65</li></ul>

运行,输出得到:

b1: 0.3618366954234483
b2: 0.5562654497238557

最小二乘法–高斯牛顿迭代法

⑥其中用到的矩阵运算代码如下:

<code class="hljs java has-numbering"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MatrixMath</span> {</span>

<span class="hljs-javadoc">/**
* 矩阵基本运算:加、减、乘、除、转置
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> OPERATION_ADD = <span class="hljs-number">1</span>;
<span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> OPERATION_SUB = <span class="hljs-number">2</span>;
<span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> OPERATION_MUL = <span class="hljs-number">4</span>;

<span class="hljs-javadoc">/**
* 矩阵加法
*<span class="hljs-javadoctag"> @param</span> a 加数
*<span class="hljs-javadoctag"> @param</span> b 被加数
*<span class="hljs-javadoctag"> @return</span> 和
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span>[][] <span class="hljs-title">plus</span>(<span class="hljs-keyword">double</span>[][] a, <span class="hljs-keyword">double</span>[][] b){
<span class="hljs-keyword">if</span>(legalOperation(a, b, OPERATION_ADD)) {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>; i<a.length; i++) {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j=<span class="hljs-number">0</span>; j<a[<span class="hljs-number">0</span>].length; j++) {
a[i][j] = a[i][j] + b[i][j];
}
}
}
<span class="hljs-keyword">return</span> a;
}

<span class="hljs-javadoc">/**
* 矩阵减法
*<span class="hljs-javadoctag"> @param</span> a 减数
*<span class="hljs-javadoctag"> @param</span> b 被减数
*<span class="hljs-javadoctag"> @return</span> 差
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span>[][] <span class="hljs-title">substract</span>(<span class="hljs-keyword">double</span>[][] a, <span class="hljs-keyword">double</span>[][] b){
<span class="hljs-keyword">if</span>(legalOperation(a, b, OPERATION_SUB)) {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>; i<a.length; i++) {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j=<span class="hljs-number">0</span>; j<a[<span class="hljs-number">0</span>].length; j++) {
a[i][j] = a[i][j] - b[i][j];
}
}
}
<span class="hljs-keyword">return</span> a;
}

<span class="hljs-javadoc">/**
* 判断矩阵行列是否符合运算
*<span class="hljs-javadoctag"> @param</span> a 进行运算的矩阵
*<span class="hljs-javadoctag"> @param</span> b 进行运算的矩阵
*<span class="hljs-javadoctag"> @param</span> type 运算类型
*<span class="hljs-javadoctag"> @return</span> 符合/不符合运算
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">legalOperation</span>(<span class="hljs-keyword">double</span>[][] a, <span class="hljs-keyword">double</span>[][] b, <span class="hljs-keyword">int</span> type) {
<span class="hljs-keyword">boolean</span> legal = <span class="hljs-keyword">true</span>;
<span class="hljs-keyword">if</span>(type == OPERATION_ADD || type == OPERATION_SUB)
{
<span class="hljs-keyword">if</span>(a.length != b.length || a[<span class="hljs-number">0</span>].length != b[<span class="hljs-number">0</span>].length) {
legal = <span class="hljs-keyword">false</span>;
}
}
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(type == OPERATION_MUL)
{
<span class="hljs-keyword">if</span>(a[<span class="hljs-number">0</span>].length != b.length) {
legal = <span class="hljs-keyword">false</span>;
}
}
<span class="hljs-keyword">return</span> legal;
}

<span class="hljs-javadoc">/**
* 矩阵乘法
*<span class="hljs-javadoctag"> @param</span> a 乘数
*<span class="hljs-javadoctag"> @param</span> b 被乘数
*<span class="hljs-javadoctag"> @return</span> 积
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span>[][] <span class="hljs-title">mult</span>(<span class="hljs-keyword">double</span>[][] a, <span class="hljs-keyword">double</span>[][] b){
<span class="hljs-keyword">if</span>(legalOperation(a, b, OPERATION_MUL)) {
<span class="hljs-keyword">double</span>[][] result = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[a.length][b[<span class="hljs-number">0</span>].length];
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>; i< a.length; i++) {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j=<span class="hljs-number">0</span>; j< b[<span class="hljs-number">0</span>].length; j++) {
result[i][j] = calculateSingleResult(a, b, i, j);
}
}
<span class="hljs-keyword">return</span> result;
}
<span class="hljs-keyword">else</span>
{
<span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
}
}

<span class="hljs-javadoc">/**
* 矩阵乘法
*<span class="hljs-javadoctag"> @param</span> a 乘数
*<span class="hljs-javadoctag"> @param</span> b 被乘数
*<span class="hljs-javadoctag"> @return</span> 积
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span>[][] <span class="hljs-title">mult</span>(<span class="hljs-keyword">double</span>[][] a, <span class="hljs-keyword">int</span> b) {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>; i<a.length; i++) {
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j=<span class="hljs-number">0</span>; j<a[<span class="hljs-number">0</span>].length; j++) {
a[i][j] = a[i][j] * b;
}
}
<span class="hljs-keyword">return</span> a;
}

<span class="hljs-javadoc">/**
* 乘数矩阵的行元素与被乘数矩阵列元素积的和
*<span class="hljs-javadoctag"> @param</span> a 乘数矩阵
*<span class="hljs-javadoctag"> @param</span> b 被乘数矩阵
*<span class="hljs-javadoctag"> @param</span> row 行
*<span class="hljs-javadoctag"> @param</span> column 列
*<span class="hljs-javadoctag"> @return</span> 值
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateSingleResult</span>(<span class="hljs-keyword">double</span>[][] a, <span class="hljs-keyword">double</span>[][] b, <span class="hljs-keyword">int</span> row, <span class="hljs-keyword">int</span> column) {
<span class="hljs-keyword">double</span> result = <span class="hljs-number">0.0</span>;
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> k = <span class="hljs-number">0</span>; k< a[<span class="hljs-number">0</span>].length; k++) {
result += a[row][k] * b[k][column];
}
<span class="hljs-keyword">return</span> result;
}

<span class="hljs-javadoc">/**
* 矩阵的转置
*<span class="hljs-javadoctag"> @param</span> a 要转置的矩阵
*<span class="hljs-javadoctag"> @return</span> 转置后的矩阵
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span>[][] <span class="hljs-title">invert</span>(<span class="hljs-keyword">double</span>[][] a){
<span class="hljs-keyword">double</span>[][] result = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[a[<span class="hljs-number">0</span>].length][a.length];
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> i=<span class="hljs-number">0</span>;i<a.length;i++){
<span class="hljs-keyword">for</span>(<span class="hljs-keyword">int</span> j=<span class="hljs-number">0</span>;j<a[<span class="hljs-number">0</span>].length;j++){
result[j][i]=a[i][j];
}
}
<span class="hljs-keyword">return</span> result;
}

<span class="hljs-javadoc">/**
* 求可逆矩阵(使用代数余子式的形式)
*/</span>
<span class="hljs-javadoc">/**
* 求传入的矩阵的逆矩阵
*<span class="hljs-javadoctag"> @param</span> value 需要转换的矩阵
*<span class="hljs-javadoctag"> @return</span> 逆矩阵
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span>[][] <span class="hljs-title">getInverseMatrix</span>(<span class="hljs-keyword">double</span>[][] value,<span class="hljs-keyword">double</span> result){
<span class="hljs-keyword">double</span>[][] transferMatrix = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[value.length][value[<span class="hljs-number">0</span>].length];
<span class="hljs-comment">//计算代数余子式,并赋值给|A| </span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < value.length; i++) {
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j < value[i].length; j++) {
transferMatrix[j][i] = mathDeterminantCalculation(getNewMatrix(i, j, value));
<span class="hljs-keyword">if</span> ((i+j)%<span class="hljs-number">2</span>!=<span class="hljs-number">0</span>) {
transferMatrix[j][i] = -transferMatrix[j][i];
}
transferMatrix[j][i] /= result;
}
}
<span class="hljs-keyword">return</span> transferMatrix;
}

<span class="hljs-javadoc">/***
* 求行列式的值
*<span class="hljs-javadoctag"> @param</span> value 需要算的行列式
*<span class="hljs-javadoctag"> @return</span> 计算的结果
*/</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span> <span class="hljs-title">mathDeterminantCalculation</span>(<span class="hljs-keyword">double</span>[][] value){
<span class="hljs-keyword">if</span> (value.length == <span class="hljs-number">1</span>) {
<span class="hljs-comment">//当行列式为1阶的时候就直接返回本身 </span>
<span class="hljs-keyword">return</span> value[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>];
}

<span class="hljs-keyword">if</span> (value.length == <span class="hljs-number">2</span>) {
<span class="hljs-comment">//如果行列式为二阶的时候直接进行计算 </span>
<span class="hljs-keyword">return</span> value[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>]*value[<span class="hljs-number">1</span>][<span class="hljs-number">1</span>]-value[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>]*value[<span class="hljs-number">1</span>][<span class="hljs-number">0</span>];
}

<span class="hljs-comment">//当行列式的阶数大于2时 </span>
<span class="hljs-keyword">double</span> result = <span class="hljs-number">1</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < value.length; i++) {
<span class="hljs-comment">//检查数组对角线位置的数值是否是0,如果是零则对该数组进行调换,查找到一行不为0的进行调换 </span>
<span class="hljs-keyword">if</span> (value[i][i] == <span class="hljs-number">0</span>) {
value = changeDeterminantNoZero(value,i,i);
result*=-<span class="hljs-number">1</span>;
}

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j <i; j++) {
<span class="hljs-comment">//让开始处理的行的首位为0处理为三角形式 </span>
<span class="hljs-comment">//如果要处理的列为0则和自己调换一下位置,这样就省去了计算 </span>
<span class="hljs-keyword">if</span> (value[i][j] == <span class="hljs-number">0</span>) {
<span class="hljs-keyword">continue</span>;
}
<span class="hljs-comment">//如果要是要处理的行是0则和上面的一行进行调换 </span>
<span class="hljs-keyword">if</span> (value[j][j]==<span class="hljs-number">0</span>) {
<span class="hljs-keyword">double</span>[] temp = value[i];
value[i] = value[i-<span class="hljs-number">1</span>];
value[i-<span class="hljs-number">1</span>] = temp;
result*=-<span class="hljs-number">1</span>;
<span class="hljs-keyword">continue</span>;
}
<span class="hljs-keyword">double</span> ratio = -(value[i][j]/value[j][j]);
value[i] = addValue(value[i],value[j],ratio);
}
}
<span class="hljs-keyword">return</span> mathValue(value,result);
}

<span class="hljs-javadoc">/**
* 计算行列式的结果
*<span class="hljs-javadoctag"> @param</span> value
*<span class="hljs-javadoctag"> @return</span>
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span> <span class="hljs-title">mathValue</span>(<span class="hljs-keyword">double</span>[][] value,<span class="hljs-keyword">double</span> result){
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < value.length; i++) {
<span class="hljs-comment">//如果对角线上有一个值为0则全部为0,直接返回结果 </span>
<span class="hljs-keyword">if</span> (value[i][i]==<span class="hljs-number">0</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
result *= value[i][i];
}
<span class="hljs-keyword">return</span> result;
}

<span class="hljs-javadoc">/***
* 将i行之前的每一行乘以一个系数,使得从i行的第i列之前的数字置换为0
*<span class="hljs-javadoctag"> @param</span> currentRow 当前要处理的行
*<span class="hljs-javadoctag"> @param</span> frontRow i行之前的遍历的行
*<span class="hljs-javadoctag"> @param</span> ratio 要乘以的系数
*<span class="hljs-javadoctag"> @return</span> 将i行i列之前数字置换为0后的新的行
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span>[] <span class="hljs-title">addValue</span>(<span class="hljs-keyword">double</span>[] currentRow,<span class="hljs-keyword">double</span>[] frontRow, <span class="hljs-keyword">double</span> ratio){
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < currentRow.length; i++) {
currentRow[i] += frontRow[i]*ratio;
}
<span class="hljs-keyword">return</span> currentRow;
}

<span class="hljs-javadoc">/**
* 指定列的位置是否为0,查找第一个不为0的位置的行进行位置调换,如果没有则返回原来的值
*<span class="hljs-javadoctag"> @param</span> determinant 需要处理的行列式
*<span class="hljs-javadoctag"> @param</span> line 要调换的行
*<span class="hljs-javadoctag"> @param</span> row 要判断的列
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span>[][] <span class="hljs-title">changeDeterminantNoZero</span>(<span class="hljs-keyword">double</span>[][] determinant,<span class="hljs-keyword">int</span> line,<span class="hljs-keyword">int</span> column){
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = line; i < determinant.length; i++) {
<span class="hljs-comment">//进行行调换 </span>
<span class="hljs-keyword">if</span> (determinant[i][column] != <span class="hljs-number">0</span>) {
<span class="hljs-keyword">double</span>[] temp = determinant[line];
determinant[line] = determinant[i];
determinant[i] = temp;
<span class="hljs-keyword">return</span> determinant;
}
}
<span class="hljs-keyword">return</span> determinant;
}

<span class="hljs-javadoc">/**
* 转换为代数余子式
*<span class="hljs-javadoctag"> @param</span> row 行
*<span class="hljs-javadoctag"> @param</span> line 列
*<span class="hljs-javadoctag"> @param</span> matrix 要转换的矩阵
*<span class="hljs-javadoctag"> @return</span> 转换的代数余子式
*/</span>
<span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span>[][] <span class="hljs-title">getNewMatrix</span>(<span class="hljs-keyword">int</span> row,<span class="hljs-keyword">int</span> line,<span class="hljs-keyword">double</span>[][] matrix){
<span class="hljs-keyword">double</span>[][] newMatrix = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[matrix.length-<span class="hljs-number">1</span>][matrix[<span class="hljs-number">0</span>].length-<span class="hljs-number">1</span>];
<span class="hljs-keyword">int</span> rowNum = <span class="hljs-number">0</span>,lineNum = <span class="hljs-number">0</span>;
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < matrix.length; i++) {
<span class="hljs-keyword">if</span> (i == row){
<span class="hljs-keyword">continue</span>;
}
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j < matrix[i].length; j++) {
<span class="hljs-keyword">if</span> (j == line) {
<span class="hljs-keyword">continue</span>;
}
newMatrix[rowNum][lineNum++%(matrix[<span class="hljs-number">0</span>].length-<span class="hljs-number">1</span>)] = matrix[i][j];
}
rowNum++;
}
<span class="hljs-keyword">return</span> newMatrix;
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span>(String[] args) {
<span class="hljs-comment">//double[][] test = {{0,0,0,1,2},{0,0,0,2,3},{1,1,0,0,0},{0,1,1,0,0},{0,0,1,0,0}}; </span>
<span class="hljs-keyword">double</span>[][] test = {
{<span class="hljs-number">3.8067488033632655</span>, -<span class="hljs-number">2.894113667134647</span>},
{-<span class="hljs-number">2.894113667134647</span>, <span class="hljs-number">3.6978894069779504</span>}
};
<span class="hljs-keyword">double</span> result;
<span class="hljs-keyword">try</span> {
<span class="hljs-keyword">double</span>[][] temp = <span class="hljs-keyword">new</span> <span class="hljs-keyword">double</span>[test.length][test[<span class="hljs-number">0</span>].length];
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < test.length; i++) {
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j < test[i].length; j++) {
temp[i][j] = test[i][j];
}
}
<span class="hljs-comment">//先计算矩阵的行列式的值是否等于0,如果不等于0则该矩阵是可逆的 </span>
result = mathDeterminantCalculation(temp);
<span class="hljs-keyword">if</span> (result == <span class="hljs-number">0</span>) {
System.out.println(<span class="hljs-string">"矩阵不可逆"</span>);
}<span class="hljs-keyword">else</span> {
System.out.println(<span class="hljs-string">"矩阵可逆"</span>);
<span class="hljs-comment">//求出逆矩阵 </span>
<span class="hljs-keyword">double</span>[][] result11 = getInverseMatrix(test,result);
<span class="hljs-comment">//打印逆矩阵 </span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i < result11.length; i++) {
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j < result11[i].length; j++) {
System.out.print(result11[i][j]+<span class="hljs-string">" "</span>);
}
System.out.println();
}
}
} <span class="hljs-keyword">catch</span> (Exception e) {
e.printStackTrace();
System.out.println(<span class="hljs-string">"不是正确的行列式!!"</span>);
}
}
}</code>