Js迭代器设计模式

188 阅读2分钟

一直以来我都觉得迭代器模式在js中毫无用武之地,直到我发现它可以用来求解方程。

以下是使用迭代器模式在 TypeScript 中实现牛顿迭代法求解实数开平方的示例代码:

  1. 首先,定义一个迭代器接口 IIterator ,它包含两个方法:hasNext()next() 。这将允许我们在迭代过程中检查是否还有下一个值,并返回迭代的下一个值。


interface IIterator {

  hasNext(): boolean;

  next(): number;

}

  1. 然后,创建一个具体的迭代器 SqrtIterator ,它实现了 IIterator 接口。在每次调用 next() 方法时,它将根据牛顿迭代法计算下一个近似值。


class SqrtIterator implements IIterator {

  private readonly number: number; // 要求解开平方的数

  private readonly epsilon: number; // 迭代精度

  private guess: number; // 初始猜测值为 number 的一半

 

  constructor(number: number, epsilon = 1e-6) {

    this.number = number;

    this.epsilon = epsilon;

    this.guess = number / 2;

  }

 

  hasNext(): boolean {

    return Math.abs(this.guess * this.guess - this.number) > this.epsilon;

  }

 

  next(): number {

    this.guess = (this.guess + this.number / this.guess) / 2;

    return this.guess;

  }

}

  1. 最后,使用 SqrtIterator 来求解实数的开平方。通过循环调用 next() 方法,直到迭代结果满足精度要求为止。


function sqrt(number: number): number {

  const iterator = new SqrtIterator(number);

  let result = 0;

  while (iterator.hasNext()) {

    result = iterator.next();

  }

  return result;

}

 

// 示例用法

console.log(sqrt(16)); // 输出:4.000000250000002

console.log(sqrt(2)); // 输出:1.4142135623746899

通过以上代码,使用迭代器模式在 TypeScript 中实现了牛顿迭代法求解实数开平方的功能。每次调用 next() 方法都会返回一个更接近实际解的近似值,直到满足精度要求为止。

  1. 改进上述代码,使之能够求解其他简单方程

next(): number {

this.guess = (this.guess + this.number / this.guess) / 2;

return this.guess;

}

修改成:

private calculator: (x: number, y: number) => number; // 外部注入

constructor(number: number, initial:number, epsilon = 1e-6, calculator: (x: number, y: number) => number) {

    this.number = number;

    this.epsilon = epsilon;

    this.guess = initial || number / 2;

    this.calculator = calculator;

}

next(): number {

    this.guess = this.calculator(this.guess, this.number);

    return this.guess;

}

验证:


function calc(number: number, initial: number, calculator: (x: number, y: number) => number): number {

    const iterator = new SqrtIterator(number, initial, undefined, calculator);

    let result = 0;

    while (iterator.hasNext()) {

        result = iterator.next();

    }

    return result;

}

// 示例用法

const sqrt: (x: number, y: number) => number = (x, y) => (x + y / x) / 2;

console.log(calc(16, 8, sqrt)); // 输出:4.000000250000002

console.log(calc(2, 1, sqrt)); // 输出:1.4142135623746899

 

 

// 对于y = x**2 + x ,已知 y = 30 求一个 x 解

// 迭代方程写成 x = y/x - 1

// 初始值取1

const exec: (x: number, y: number) => number = (x, y) => y/x - 1;

console.log(calc(30, 1, exec)); // 本来应该输出5的,可惜它发散了,发散了挺好的,更加加深印象