Harmonyos应用实例221:数列通项与求和计算器
·
3. 数列通项与求和计算器
功能简介:支持等差数列、等比数列的通项公式和前n项和计算,通过可视化展示数列的增长趋势。支持自定义数列类型,计算通项公式、求和公式,以及极限分析,帮助学生理解数列的基本概念和性质。
ArkTS代码:
@Entry
@Component
struct SequenceCalculator {
@State private sequenceType: string = 'arithmetic'
@State private a1: number = 1
@State private d: number = 2
@State private n: number = 10
@State private result: string = ''
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
build() {
Column() {
Text('🔢 数列通项与求和计算器')
.fontSize(24).fontWeight(FontWeight.Bold)
.margin({ bottom: 20 })
Text('数列类型')
.fontSize(18).fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Row() {
Button('等差数列')
.width(100)
.onClick(() => {
this.sequenceType = 'arithmetic'
this.calculate()
})
Button('等比数列')
.width(100)
.onClick(() => {
this.sequenceType = 'geometric'
this.calculate()
})
}
Text('数列参数')
.fontSize(18).fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
Row() {
Text('首项 a₁: ')
.width(70)
TextInput({
placeholder: '首项',
text: this.a1.toString()
})
.width(100)
.onChange((v: string) => {
this.a1 = parseFloat(v) || 0
this.calculate()
})
}
.margin({ bottom: 10 })
Row() {
Text(this.sequenceType === 'arithmetic' ? '公差 d: ' : '公比 q: ')
.width(70)
TextInput({
placeholder: this.sequenceType === 'arithmetic' ? '公差' : '公比',
text: this.d.toString()
})
.width(100)
.onChange((v: string) => {
this.d = parseFloat(v) || 0
this.calculate()
})
}
.margin({ bottom: 20 })
Text('计算设置')
.fontSize(18).fontWeight(FontWeight.Bold)
.margin({ bottom: 10 })
Row() {
Text('项数 n: ')
.width(60)
Slider({ value: this.n, min: 1, max: 20, step: 1 })
.width(200)
.onChange((val: number) => {
this.n = val
this.calculate()
})
Text(this.n.toString())
.width(40)
}
Button('计算')
.width(100)
.margin({ top: 20, bottom: 20 })
.onClick(() => this.calculate())
Canvas(this.context)
.width(400).height(300)
.backgroundColor('#f5f5f5')
.onReady(() => this.drawSequence())
Text('计算结果')
.fontSize(18).fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
Text(this.result)
.fontSize(16).fontColor('#2196F3')
Text('数列公式')
.fontSize(18).fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
Text(this.getSequenceFormulas())
.fontSize(14).fontColor('#666')
Text('极限分析')
.fontSize(18).fontWeight(FontWeight.Bold)
.margin({ top: 20, bottom: 10 })
Text(this.getLimitAnalysis())
.fontSize(14).fontColor('#666')
}
.padding(20)
}
private calculate() {
if (this.sequenceType === 'arithmetic') {
const an = this.a1 + (this.n - 1) * this.d
const sn = this.n * (this.a1 + an) / 2
this.result = `第${this.n}项: ${an}, 前${this.n}项和: ${sn}`
} else {
const an = this.a1 * Math.pow(this.d, this.n - 1)
let sn: number
if (this.d === 1) {
sn = this.n * this.a1
} else {
sn = this.a1 * (1 - Math.pow(this.d, this.n)) / (1 - this.d)
}
this.result = `第${this.n}项: ${an.toFixed(2)}, 前${this.n}项和: ${sn.toFixed(2)}`
}
this.drawSequence()
}
private drawSequence() {
const ctx = this.context
const width = 400
const height = 300
const padding = 50
// 清空画布
ctx.clearRect(0, 0, width, height)
// 绘制坐标轴
ctx.beginPath()
ctx.moveTo(padding, height - padding)
ctx.lineTo(width - padding, height - padding)
ctx.moveTo(padding, padding)
ctx.lineTo(padding, height - padding)
ctx.strokeStyle = '#000'
ctx.lineWidth = 1
ctx.stroke()
// 计算数列值
const values: number[] = []
for (let i = 1; i <= this.n; i++) {
if (this.sequenceType === 'arithmetic') {
values.push(this.a1 + (i - 1) * this.d)
} else {
values.push(this.a1 * Math.pow(this.d, i - 1))
}
}
// 计算缩放因子
const maxValue = Math.max(...values.map(Math.abs)) || 1
const yScale = (height - 2 * padding) / (2 * maxValue)
const xScale = (width - 2 * padding) / (this.n - 1 || 1)
// 绘制数列点和连线
ctx.beginPath()
ctx.strokeStyle = '#2196F3'
ctx.lineWidth = 2
for (let i = 0; i < values.length; i++) {
const x = padding + i * xScale
const y = height - padding - values[i] * yScale
// 绘制点
ctx.beginPath()
ctx.arc(x, y, 5, 0, 2 * Math.PI)
ctx.fillStyle = '#2196F3'
ctx.fill()
ctx.strokeStyle = '#000'
ctx.stroke()
// 绘制连线
if (i > 0) {
const prevX = padding + (i - 1) * xScale
const prevY = height - padding - values[i - 1] * yScale
ctx.beginPath()
ctx.moveTo(prevX, prevY)
ctx.lineTo(x, y)
ctx.strokeStyle = '#2196F3'
ctx.stroke()
}
// 绘制坐标
ctx.font = '12px Arial'
ctx.fillStyle = '#000'
ctx.fillText((i + 1).toString(), x - 5, height - padding + 15)
ctx.fillText(values[i].toFixed(1), x - 15, y - 10)
}
}
private getSequenceFormulas(): string {
if (this.sequenceType === 'arithmetic') {
return `通项公式: aₙ = a₁ + (n-1)d\n` +
`前n项和: Sₙ = n(a₁ + aₙ)/2 = na₁ + n(n-1)d/2`
} else {
return `通项公式: aₙ = a₁·qⁿ⁻¹\n` +
`前n项和: Sₙ = a₁(1-qⁿ)/(1-q) (q≠1)\n` +
`前n项和: Sₙ = na₁ (q=1)`
}
}
private getLimitAnalysis(): string {
if (this.sequenceType === 'arithmetic') {
if (this.d === 0) {
return `极限: lim(n→∞) aₙ = a₁ (常数数列)`
} else if (this.d > 0) {
return `极限: lim(n→∞) aₙ = +∞ (递增数列)`
} else {
return `极限: lim(n→∞) aₙ = -∞ (递减数列)`
}
} else {
if (Math.abs(this.d) < 1) {
return `极限: lim(n→∞) aₙ = 0 (收敛数列)`
} else if (Math.abs(this.d) === 1) {
if (this.d === 1) {
return `极限: lim(n→∞) aₙ = a₁ (常数数列)`
} else {
return `极限: 不存在 (振荡数列)`
}
} else {
return `极限: lim(n→∞) aₙ = ∞ (发散数列)`
}
}
}
}
更多推荐



所有评论(0)