鸿蒙 ArkTS 实战|二元一次方程组应用:两直线交点求解 + 三种解的可视化判定

在这里插入图片描述
在这里插入图片描述

一、设计思路

二元一次方程组的几何意义就是两条直线的交点。本页做成"直线可视化求解器":输入两条直线 y = k₁x + b₁、y = k₂x + b₂,代码算出交点坐标,Canvas 同时画出两条直线并标记交点;斜率截距不同的组合,自动给出唯一解 / 无解 / 无穷多解三种结论,让"解的数量"变成看得见的几何关系。

二、状态与求解逻辑(含三种解判定)

import { router } from '@kit.ArkUI';

interface Pixel { px: number; py: number; }

@Entry
@Component
struct BinaryEquation {
  @State k1: number = 1;            // 直线1 斜率
  @State b1: number = 0;            // 直线1 截距
  @State k2: number = -1;           // 直线2 斜率
  @State b2: number = 4;            // 直线2 截距
  @State solutionState: string = '唯一解';
  @State solution: string = 'x = 2.00, y = 2.00';

  private settings: RenderingContextSettings = new RenderingContextSettings(true);
  private ctx: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings);

  // 解方程组:两式相减消 y,得 (k1 - k2)x = b2 - b1
  private solve(): void {
    const d = this.k1 - this.k2;
    if (Math.abs(d) < 0.0001) {
      // k 相等:斜率相同 → 平行或重合
      if (Math.abs(this.b1 - this.b2) < 0.0001) {
        this.solutionState = '重合 · 无穷多解';
        this.solution = '两条直线完全重合,处处都是解';
      } else {
        this.solutionState = '平行 · 无解';
        this.solution = '两条直线平行,永不相交';
      }
    } else {
      // k 不等:必然相交,交点即唯一解
      const x = (this.b2 - this.b1) / d;
      const y = this.k1 * x + this.b1;
      this.solutionState = '唯一解';
      this.solution = 'x = ' + x.toFixed(2) + ',  y = ' + y.toFixed(2);
    }
  }

  private yOf1(x: number): number { return this.k1 * x + this.b1; }
  private yOf2(x: number): number { return this.k2 * x + this.b2; }
}

三、三种解的判定逻辑表

k₁ 与 k₂b₁ 与 b₂几何关系解的数量
k₁ ≠ k₂任意两条直线相交唯一解(交点坐标)
k₁ = k₂b₁ ≠ b₂平行无解
k₁ = k₂b₁ = b₂完全重合无穷多解

代码用 Math.abs(d) < 0.0001 做浮点相等判断(而不是 ===),避免因浮点误差把"相等"误判为"不等"。

四、Canvas 绘制两条直线与交点

  // 世界坐标 → 画布像素(画布中心即原点)
  private toPixel(x: number, y: number, w: number, h: number): Pixel {
    return {
      px: w / 2 + (x / this.xRange) * (w / 2),
      py: h / 2 - (y / this.yRange) * (h / 2)
    };
  }

  private drawLines(): void {
    const ctx = this.ctx;
    const w = ctx.width;
    const h = ctx.height;
    ctx.clearRect(0, 0, w, h);

    // 网格与坐标轴(与一元页同构,略)
    // 直线1(蓝):取 x = ±6 两端点连线
    const lp1a = this.toPixel(-this.xRange, this.yOf1(-this.xRange), w, h);
    const lp1b = this.toPixel(this.xRange, this.yOf1(this.xRange), w, h);
    ctx.strokeStyle = '#4C7DFF';
    ctx.lineWidth = 3;
    ctx.beginPath(); ctx.moveTo(lp1a.px, lp1a.py); ctx.lineTo(lp1b.px, lp1b.py); ctx.stroke();

    // 直线2(橙):同上
    const lp2a = this.toPixel(-this.xRange, this.yOf2(-this.xRange), w, h);
    const lp2b = this.toPixel(this.xRange, this.yOf2(this.xRange), w, h);
    ctx.strokeStyle = '#F59E0B';
    ctx.lineWidth = 3;
    ctx.beginPath(); ctx.moveTo(lp2a.px, lp2a.py); ctx.lineTo(lp2b.px, lp2b.py); ctx.stroke();

    // 交点:仅唯一解时绘制红色圆点 + 坐标标签
    const d = this.k1 - this.k2;
    if (Math.abs(d) >= 0.0001) {
      const x = (this.b2 - this.b1) / d;
      const y = this.k1 * x + this.b1;
      const ip = this.toPixel(x, y, w, h);
      ctx.beginPath(); ctx.arc(ip.px, ip.py, 6, 0, Math.PI * 2);
      ctx.fillStyle = '#EF4444';
      ctx.fill();
      ctx.strokeStyle = Color.White;
      ctx.lineWidth = 2;
      ctx.stroke();
      ctx.fillStyle = '#EF4444';
      ctx.fillText('(' + x.toFixed(1) + ', ' + y.toFixed(1) + ')', ip.px + 12, ip.py - 10);
    }
  }

五、UI 组装(四参数输入 + 解结果卡)

  build() {
    Column() {
      // 顶部标题栏(略)
      Scroll() {
        Column({ space: 14 }) {
          // 方程组公式卡
          Text('y = k₁x + b₁ / y = k₂x + b₂')
            .fontSize(17).fontWeight(FontWeight.Bold)
            .fontColor('#7C3AED').width('100%').textAlign(TextAlign.Center)

          // 两直线 + 交点
          Canvas(this.ctx)
            .width('100%').height(230)
            .onReady(() => { this.drawLines(); })

          // 解结果卡(自动刷新)
          Row({ space: 10 }) {
            Text(this.solutionState)
              .fontSize(13).fontColor(Color.White)
              .backgroundColor('#7C3AED')
              .padding({ left: 10, right: 10, top: 4, bottom: 4 })
              .borderRadius(10)
            Text(this.solution)
              .fontSize(14).fontWeight(FontWeight.Bold).fontColor('#111827')
          }.width('100%')

          // 四参数输入区:改任一参数 → solve() + drawLines()
          Row({ space: 10 }) {
            Text('k₁ =').fontSize(14).fontColor('#111827')
            TextInput({ text: this.k1.toString() })
              .width(70).height(36).type(InputType.Number)
              .onChange((v: string) => {
                this.k1 = Number(v) || 0;
                this.solve();
                this.drawLines();
              })
            Text('b₁ =').fontSize(14).fontColor('#111827')
            TextInput({ text: this.b1.toString() })
              .width(70).height(36).type(InputType.Number)
              .onChange((v: string) => {
                this.b1 = Number(v) || 0;
                this.solve();
                this.drawLines();
              })
            Blank()
          }.width('100%')
          // k₂、b₂ 输入行同构(略)
        }
        .padding(14)
      }
      .layoutWeight(1).scrollBar(BarState.Off)
    }
    .height('100%').width('100%').backgroundColor('#F4F6FA')
  }

六、代码要点

  • 消元思想代码化(k1 - k2)x = b2 - b1 正是加减消元法的代码形态,x = (b2 - b1) / (k1 - k2)
  • 浮点容差:斜率差用 Math.abs(d) < 0.0001 判断,而不是直接 d === 0,杜绝浮点误差误判。
  • 几何到代数闭环:改参数 → solve() 算解 → drawLines() 画交点,图形与文字永远一致。
  • 两直线一画:直线1、直线2 分别用蓝、橙双色,交点用红点 + 白描边 + 坐标标签,视觉层次清晰。

七、二元一次方程组核心知识点

要点内容
定义含有两个未知数,且未知数次数都为 1 的两个方程合在一起
几何意义每个方程是一条直线,方程组的解 = 两直线的交点
代入法用一个方程解出 x(或 y),代入另一个方程消元
加减法两式相加减消去一个未知数(系数相等或相反时最方便)
解的情况相交唯一解、平行无解、重合无穷多解
检验把解代入两个方程都成立才是正确解
易错平行 ≠ 重合;消元时注意符号变化
口诀二元方程两条线,交点坐标就是解;k 同 b 异两平行,k 同 b 同无数解
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值