HarmonyOS鸿蒙Next数学类上架项目解析6-矩阵行列式计算

HarmonyOS鸿蒙Next数学类上架项目解析6-矩阵行列式计算 在开发鸿蒙数学计算应用时,需要实现矩阵行列式的计算功能。要求:

  1. 支持任意n阶方阵的行列式计算
  2. 使用递归展开法(拉普拉斯展开)
  3. 对于小阶矩阵使用直接公式优化性能

如何用ArkTS实现一个矩阵行列式计算器?

3 回复

行列式是方阵的一个重要数值特征,计算方法主要有:

- 2阶:|A| = a₁₁a₂₂ - a₁₂a₂₁

- 3阶:萨鲁斯法则(对角线法则)

- n阶:拉普拉斯展开(按某行/列展开)

拉普拉斯展开公式:det(A) = Σ aᵢⱼ × (-1)^(i+j) × Mᵢⱼ

1. 定义数据模型

// 矩阵类型
type Matrix = number[][]
// 计算结果接口
interface DeterminantResult {
  value: number           // 行列式值
  size: number            // 矩阵阶数
  isValid: boolean        // 是否有效
  errorMsg?: string       // 错误信息
}

2. 核心计算函数

  验证是否为有效方阵
  @param matrix 输入矩阵
  @returns 是否有效
function isValidSquareMatrix(matrix: Matrix): boolean {
  if (!matrix || matrix.length === 0) {
    return false
  }

  const n: number = matrix.length
  for (let i = 0; i < n; i++) {
    if (!matrix[i] || matrix[i].length !== n) {
      return false
    }
  }
  return true
}
  获取余子式矩阵(删除第row行第col列)
  @param matrix 原矩阵
  @param row 删除的行
  @param col 删除的列
  @returns 余子式矩阵
function getMinorMatrix(matrix: Matrix, row: number, col: number): Matrix {
  const n: number = matrix.length
  const minor: Matrix = []

  for (let i = 0; i < n; i++) {
    if (i === row) continue

    const newRow: number[] = []
    for (let j = 0; j < n; j++) {
      if (j === col) continue
      newRow.push(matrix[i][j])
    }
    minor.push(newRow)
  }

  return minor
}
  计算2阶行列式
function det2x2(matrix: Matrix): number {
  return matrix[0][0] * matrix[1][1] - matrix[0][1] * matrix[1][0]
}
  计算3阶行列式(萨鲁斯法则)
function det3x3(matrix: Matrix): number {
  const a = matrix
  return (
    a[0][0] * a[1][1] * a[2][2] +
    a[0][1] * a[1][2] * a[2][0] +
    a[0][2] * a[1][0] * a[2][1] -
    a[0][2] * a[1][1] * a[2][0] -
    a[0][1] * a[1][0] * a[2][2] -
    a[0][0] * a[1][2] * a[2][1]
  )
}
  递归计算n阶行列式(拉普拉斯展开)
  @param matrix 方阵
  @returns 行列式值
function determinant(matrix: Matrix): number {
  const n: number = matrix.length

  // 1阶矩阵
  if (n === 1) {
    return matrix[0][0]
  }

  // 2阶矩阵直接计算
  if (n === 2) {
    return det2x2(matrix)
  }

  // 3阶矩阵使用萨鲁斯法则
  if (n === 3) {
    return det3x3(matrix)
  }

  // n阶矩阵使用拉普拉斯展开(按第一行展开)
  let det: number = 0
  for (let j = 0; j < n; j++) {
    const sign: number = Math.pow(-1, j)
    const minor: Matrix = getMinorMatrix(matrix, 0, j)
    det += sign * matrix[0][j] * determinant(minor)
  }

  return det
}
  计算矩阵行列式(带验证)
  @param matrix 输入矩阵
  @returns 计算结果
function calculateDeterminant(matrix: Matrix): DeterminantResult {
  // 验证输入
  if (!isValidSquareMatrix(matrix)) {
    return {
      value: 0,
      size: 0,
      isValid: false,
      errorMsg: '请输入有效的方阵'
    }
  }

  const n: number = matrix.length

  // 检查是否包含无效数值
  for (let i = 0; i < n; i++) {
    for (let j = 0; j < n; j++) {
      if (Number.isNaN(matrix[i][j]) || !Number.isFinite(matrix[i][j])) {
        return {
          value: 0,
          size: n,
          isValid: false,
          errorMsg: '矩阵包含无效数值'
        }
      }
    }
  }

  try {
    const det: number = determinant(matrix)
    return {
      value: det,
      size: n,
      isValid: true
    }
  } catch (error) {
    return {
      value: 0,
      size: n,
      isValid: false,
      errorMsg: '计算过程出错'
    }
  }
}

3. 矩阵输入解析

  从字符串解析矩阵
  格式:每行用分号分隔,每个元素用逗号分隔
  例如:"1,2,3;4,5,6;7,8,9"
function parseMatrix(input: string): Matrix | null {
  try {
    const rows: string[] = input.trim().split(';')
    const matrix: Matrix = []

    for (const row of rows) {
      const elements: number[] = row.split(',').map(s => parseFloat(s.trim()))
      if (elements.some(e => Number.isNaN(e))) {
        return null
      }
      matrix.push(elements)
    }

    return matrix
  } catch (error) {
    return null
  }
}
  矩阵转字符串显示
function matrixToString(matrix: Matrix): string {
  return matrix.map(row => row.join('\t')).join('\n')
}

4. 完整UI组件实现

@Entry
@Component
struct DeterminantCalculator {
  @State matrixSize: number = 3
  @State matrixInput: string = '1,2,3;4,5,6;7,8,9'
  @State result: DeterminantResult | null = null
  @State parsedMatrix: Matrix | null = null

  build() {
    Column() {
      Text('矩阵行列式计算器')
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .margin({ bottom: 10 })

      Text('拉普拉斯展开法')
        .fontSize(14)
        .fontColor('#666666')
        .margin({ bottom: 20 })

      // 矩阵阶数选择
      Row() {
        Text('矩阵阶数:')
        Button('2×2').onClick(() => this.setMatrixSize(2))
          .backgroundColor(this.matrixSize === 2 ? '#007AFF' : '#E0E0E0')
          .margin({ right: 8 })
        Button('3×3').onClick(() => this.setMatrixSize(3))
          .backgroundColor(this.matrixSize === 3 ? '#007AFF' : '#E0E0E0')
          .margin({ right: 8 })
        Button('4×4').onClick(() => this.setMatrixSize(4))
          .backgroundColor(this.matrixSize === 4 ? '#007AFF' : '#E0E0E0')
      }
      .margin({ bottom: 15 })

      // 矩阵输入
      Text('输入矩阵(行用分号分隔,元素用逗号分隔):')
        .fontSize(14)
        .margin({ bottom: 8 })

      TextArea({ text: this.matrixInput })
        .width('100%')
        .height(100)
        .onChange((value: string) => {
          this.matrixInput = value
          this.parsedMatrix = parseMatrix(value)
        })
        .margin({ bottom: 10 })

      // 矩阵预览
      if (this.parsedMatrix) {
        Column() {
          Text('矩阵预览:')
            .fontSize(14)
            .margin({ bottom: 8 })
          Text(matrixToString(this.parsedMatrix))
            .fontFamily('monospace')
            .fontSize(16)
        }
        .padding(12)
        .backgroundColor('#f0f0f0')
        .borderRadius(8)
        .margin({ bottom: 15 })
      }

      // 计算按钮
      Button('计算行列式')
        .onClick(() => this.handleCalculate())
        .width(200)
        .margin({ bottom: 20 })

      // 结果显示
      if (this.result) {
        Column() {
          if (this.result.isValid) {
            Text(`${this.result.size}阶矩阵行列式:`)
              .fontSize(16)
              .margin({ bottom: 8 })
            Text(`det(A) = ${this.result.value}`)
              .fontSize(24)
              .fontWeight(FontWeight.Bold)
              .fontColor('#007AFF')
          } else {
            Text(this.result.errorMsg || '计算错误')
              .fontColor(Color.Red)
          }
        }
        .padding(16)
        .backgroundColor('#f5f5f5')
        .borderRadius(8)
      }
    }
    .width('100%')
    .height('100%')
    .padding(20)
  }

  setMatrixSize(size: number): void {
    this.matrixSize = size
    // 生成示例矩阵
    const examples: Map<number, string> = new Map([
      [2, '1,2;3,4'],
      [3, '1,2,3;4,5,6;7,8,9'],
      [4, '1,2,3,4;5,6,7,8;9,10,11,12;13,14,15,16']
    ])
    this.matrixInput = examples.get(size) || ''
    this.parsedMatrix = parseMatrix(this.matrixInput)
  }

  handleCalculate(): void {
    const matrix = parseMatrix(this.matrixInput)
    if (matrix) {
      this.result = calculateDeterminant(matrix)
    } else {
      this.result = {
        value: 0,
        size: 0,
        isValid: false,
        errorMsg: '矩阵格式错误'
      }
    }
  }
}

5. 使用示例

// 示例1:2阶矩阵 // |1 2| // |3 4| = 1×4 - 2×3 = -2 const matrix2: Matrix = [[1, 2], [3, 4]] const result1 = calculateDeterminant(matrix2) // { value: -2, size: 2, isValid: true }

// 示例2:3阶矩阵 // |1 2 3| // |4 5 6| = 0(行列式为0,矩阵奇异) // |7 8 9| const matrix3: Matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] const result2 = calculateDeterminant(matrix3) // { value: 0, size: 3, isValid: true }

// 示例3:3阶单位矩阵 // |1 0 0| // |0 1 0| = 1 // |0 0 1| const identity: Matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]] const result3 = calculateDeterminant(identity) // { value: 1, size: 3, isValid: true }

总结

使用ArkTS实现矩阵行列式计算的关键点:

  1. 对于2阶和3阶矩阵使用直接公式,效率更高
  2. n阶矩阵使用拉普拉斯展开,时间复杂度为O(n!)
  3. 递归计算时需要正确处理代数余子式的符号(-1)^(i+j)
  4. 行列式为0表示矩阵奇异(不可逆)
  5. 对于大型矩阵,可以考虑使用LU分解等更高效的算法
  6. 项目链接:https://gitee.com/solgull/math-fbox

更多关于HarmonyOS鸿蒙Next数学类上架项目解析6-矩阵行列式计算的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


鸿蒙Next数学类库提供Matrix类用于矩阵运算。行列式计算可通过Matrix.determinant()方法实现,该方法基于LU分解算法,支持2x2、3x3及更高阶方阵。调用时需确保矩阵为方阵,否则会抛出IllegalArgumentException异常。具体实现可参考HarmonyOS API文档中Matrix类的相关说明。

在HarmonyOS Next中使用ArkTS实现矩阵行列式计算器,可通过递归展开法结合小阶矩阵优化来实现。以下是核心实现方案:

1. 数据结构定义

class Matrix {
  data: number[][];
  constructor(data: number[][]) {
    this.data = data;
  }
}

2. 小阶矩阵优化计算

private determinant2x2(mat: Matrix): number {
  return mat.data[0][0] * mat.data[1][1] - mat.data[0][1] * mat.data[1][0];
}

private determinant3x3(mat: Matrix): number {
  const a = mat.data;
  return a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1])
    - a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0])
    + a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]);
}

3. 递归展开主函数

calculateDeterminant(mat: Matrix): number {
  const n = mat.data.length;
  
  // 小阶矩阵直接计算
  if (n === 1) return mat.data[0][0];
  if (n === 2) return this.determinant2x2(mat);
  if (n === 3) return this.determinant3x3(mat);
  
  let det = 0;
  // 按第一行展开
  for (let j = 0; j < n; j++) {
    const subMatrix = this.getSubMatrix(mat, 0, j);
    const sign = (j % 2 === 0) ? 1 : -1;
    det += sign * mat.data[0][j] * this.calculateDeterminant(subMatrix);
  }
  return det;
}

4. 子矩阵生成函数

private getSubMatrix(mat: Matrix, row: number, col: number): Matrix {
  const n = mat.data.length;
  const subData: number[][] = [];
  
  for (let i = 0; i < n; i++) {
    if (i === row) continue;
    const newRow: number[] = [];
    for (let j = 0; j < n; j++) {
      if (j === col) continue;
      newRow.push(mat.data[i][j]);
    }
    subData.push(newRow);
  }
  return new Matrix(subData);
}

5. 性能优化建议

  • 对于4阶及以下矩阵使用硬编码公式
  • 添加矩阵奇异性检查,行列式为0时提前返回
  • 可考虑使用LU分解法作为备选算法提升大矩阵性能

6. 使用示例

const matrix = new Matrix([
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9]
]);
const det = calculator.calculateDeterminant(matrix);

此实现通过递归展开满足n阶方阵计算需求,同时针对小阶矩阵优化避免了不必要的递归开销。

回到顶部