You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ada语言矩阵求逆代码格式问题求助:文件读取与计算故障排查

Ada矩阵求逆代码问题排查

我是Ada语言新手,编写的矩阵求逆代码存在问题但无法定位原因。代码目标是读取a.txt和b.txt两个文件,计算矩阵的逆并求解线性方程组。

输入文件内容

A.txt

2 -2 4 -2 2 0 
1 0 4 -3 0 0
1 1 1 1 1 1 
1 0 0 -1 0 0
3 0 0 -3 0 2
1 0 0 0 -2 4

B.txt

13
18
51
82
32
12

我的代码

with Ada.Text_IO, Ada.Float_Text_IO, Ada.Integer_Text_IO;
use Ada.Text_IO, Ada.Float_Text_IO, Ada.Integer_Text_IO;

procedure Matrix_Inverse is

   type Matrix is array (1 .. 6, 1 .. 6) of Float;
   type Vector is array (1 .. 6) of Float;
   
   function Get_Matrix_From_File(Filename : String) return Matrix is
      A : Matrix := (others => (others => 0.0));
      File : File_Type;
      Line : String (1 .. 20);
      Last : Natural;
   begin
      Open (File, In_File, Filename);
      for I in A'Range(1) loop
         Get_Line (File, Line, Last);
         for J in A'Range(2) loop
            A (I, J) := Float'Value (Line (1 .. Last));
            Get (File, Line);
            Get_Line (File, Line, Last);
         end loop;
         A (I, 6) := Float'Value (Line (1 .. Last));
      end loop;
      Close (File);
      return A;
   end Get_Matrix_From_File;
   
   function Get_Vector_From_File(Filename : String) return Vector is
      B : Vector := (others => 0.0);
      File : File_Type;
   begin
      Open (File, In_File, Filename);
      for I in B'Range loop
         Get (File, B (I));
      end loop;
      Close (File);
      return B;
   end Get_Vector_From_File;
   
   procedure Print_Matrix(A : Matrix) is
   begin
      for I in A'Range(1) loop
         for J in A'Range(2) loop
            Put (A (I, J), 6, 2);
            Put (" ");
         end loop;
         New_Line;
      end loop;
   end Print_Matrix;
   
   function Inverse(A : Matrix) return Matrix is
      Inv : Matrix := (others => (others => 0.0));
      Identity : Matrix := (others => (others => 0.0));
   begin
      for I in Identity'Range(1) loop
         Identity (I, I) := 1.0;
      end loop;
      
      for I in A'Range(1) loop
         if A (I, I) = 0.0 then
            for J in I + 1 .. A'Range(1)'Last loop
               if A (J, I) /= 0.0 then
                  for K in A'Range(2) loop
                     A (I, K) := A (I, K) + A (J, K);
                     Identity (I, K) := Identity (I, K) + Identity (J, K);
                  end loop;
                  exit;
               end if;
            end loop;
         end if;
    for J in A'Range(1) loop
      if J /= I then
          declare
            Factor : constant Float := A (J, I) / A (I, I);
          begin
            for K in A'Range(2) loop
                A (J, K) := A (J, K) - Factor * A (I, K);
                Identity (J, K) := Identity (J, K) - Factor * Identity (I, K);
            end loop;
          end;
      end if;
    end loop;

    for I in A'Range(1) loop
      declare
          Diagonal : constant Float := A (I, I);
      begin
          for J in A'Range(2) loop
            Identity (I, J) := Identity (I, J) / Diagonal;
          end loop;
      end;
    end loop;

      return Identity;
    end Inverse;

  function Solve(A : Matrix; B : Vector) return Vector is
    Inv_A : Matrix := Inverse(A);
    Result : Vector := (others => 0.0);
  begin
    for I in Result'Range loop
        for J in Result'Range loop
          Result (I) := Result (I) + Inv_A (I, J) * B (J);
        end loop;
    end loop;
    return Result;
  end Solve;

  A : Matrix := Get_Matrix_From_File("a.txt");
  B : Vector := Get_Vector_From_File("b.txt");

  Solution : Vector := Solve(A, B);

  begin
    Put_Line("Solution:");
    for I in Solution'Range loop
        Put(Solution(I), 6, 2);
        Put(" ");
    end loop;
    New_Line;
end Matrix_Inverse;

代码问题及修正方案

1. 矩阵读取逻辑完全错误

Get_Matrix_From_File的读取逻辑混乱,错误使用Get_Line和Get导致矩阵值读取错误。简化为直接读取数值即可:

function Get_Matrix_From_File(Filename : String) return Matrix is
   A : Matrix := (others => (others => 0.0));
   File : File_Type;
begin
   Open (File, In_File, Filename);
   for I in A'Range(1) loop
      for J in A'Range(2) loop
         Get (File, A(I, J));
      end loop;
   end loop;
   Close (File);
   return A;
end Get_Matrix_From_File;

2. 函数输入参数只读冲突

Ada函数的输入参数默认是只读模式,Inverse函数中直接修改参数A会导致编译错误。需创建参数副本操作:

function Inverse(Original_A : Matrix) return Matrix is
   A : Matrix := Original_A; -- 创建副本
   Identity : Matrix := (others => (others => 0.0));
begin
   -- 后续逻辑使用A而非Original_A

3. 主元处理逻辑漏洞

  • 主元为0时,仅将下方行加到当前行而非直接交换,会导致计算异常,应改为直接互换两行:
    if abs A(I, I) < 1.0e-6 then -- 用精度阈值替代直接等于0
       for J in I + 1 .. A'Range(1)'Last loop
          if abs A(J, I) > 1.0e-6 then
             -- 交换I行和J行
             declare
                Temp : Float;
             begin
                for K in A'Range(2) loop
                   Temp := A(I, K);
                   A(I, K) := A(J, K);
                   A(J, K) := Temp;
                   Temp := Identity(I, K);
                   Identity(I, K) := Identity(J, K);
                   Identity(J, K) := Temp;
                end loop;
                exit;
             end;
          end if;
       end loop;
    end if;
    
  • 高斯-约当消元步骤顺序错误,应先完成所有行的消元,再进行主元归一化,或按列先归一化再消元。

4. 浮点数精度问题

直接用A(I,I) = 0.0判断主元会因为精度误差误判,改用极小阈值比较:abs A(I,I) < 1.0e-6。

5. 变量初始化顺序问题

Solution : Vector := Solve(A, B);放在声明区虽合法,但更规范的做法是移到begin块内,避免初始化顺序潜在问题。


内容的提问来源于stack exchange,提问作者lga2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 05:35:01