KMP 实现鸿蒙跨端:Kotlin 斐波那契数列计算器
本文介绍了基于Kotlin Multiplatform(KMP)的跨端斐波那契数列计算器实现方案。该工具能够在鸿蒙系统中运行,支持生成1-50项的斐波那契数列,并提供多维分析功能,包括基础统计、奇偶分析、质数识别、黄金比例计算和增长率分析等核心功能。文章详细展示了Kotlin实现的关键代码片段,如数列生成算法、质数检查函数和黄金比例计算逻辑,并提供了一个完整的实战案例。该方案通过KMP技术实现了代
·
KMP 实现鸿蒙跨端:Kotlin 斐波那契数列计算器
目录
概述
本文档介绍如何在 Kotlin Multiplatform (KMP) 鸿蒙跨端开发中实现一个完整的斐波那契数列计算器系统。这个案例展示了如何使用 Kotlin 的数学计算、集合操作和算法实现来创建一个功能丰富的数列分析工具。通过 KMP,这个工具可以无缝编译到 JavaScript,在 OpenHarmony 应用中运行,并支持用户输入进行实时处理。
工具的特点
- 数列生成:快速生成指定长度的斐波那契数列
- 多维度分析:从多个角度分析数列特性
- 数学计算:计算统计值、比率、增长率等
- 质数识别:识别数列中的质数
- 黄金比例:展示黄金比例的数学美妙
- 跨端兼容:一份 Kotlin 代码可同时服务多个平台
工具功能
1. 数列生成
- 项数范围:支持 1-50 项
- 数列显示:完整显示生成的斐波那契数列
- 性能优化:使用高效的迭代算法
2. 基础统计
- 总和:计算数列中所有数字的和
- 平均值:计算数列的平均值
- 最大值:找出数列中的最大值
- 最小值:找出数列中的最小值
3. 奇偶分析
- 偶数个数:统计偶数的个数
- 奇数个数:统计奇数的个数
- 奇偶分布:展示奇偶数的分布规律
4. 质数分析
- 质数识别:识别数列中的所有质数
- 质数列表:显示所有质数
- 质数个数:统计质数的个数
5. 黄金比例分析
- 相邻比率:计算相邻项的比率
- 平均比率:计算所有比率的平均值
- 理论值对比:与黄金比例 1.618034 对比
- 比率列表:显示前 5 个比率
6. 增长率分析
- 增长率计算:计算相邻项的增长率
- 平均增长率:计算平均增长率
- 增长趋势:展示增长的加速趋势
核心实现
1. 斐波那契数列生成
val fibonacci = mutableListOf<Long>()
if (n >= 1) fibonacci.add(0)
if (n >= 2) fibonacci.add(1)
for (i in 2 until n) {
fibonacci.add(fibonacci[i - 1] + fibonacci[i - 2])
}
2. 基础统计
val sum = fibonacci.sum()
val average = if (fibonacci.isNotEmpty()) sum / fibonacci.size else 0L
val max = fibonacci.maxOrNull() ?: 0L
val min = fibonacci.minOrNull() ?: 0L
3. 奇偶分析
val isEven = fibonacci.count { it % 2L == 0L }
val isOdd = fibonacci.count { it % 2L != 0L }
4. 质数检查
fun isPrime(n: Long): Boolean {
if (n <= 1) return false
if (n <= 3) return true
if (n % 2 == 0L || n % 3 == 0L) return false
var i = 5L
while (i * i <= n) {
if (n % i == 0L || n % (i + 2) == 0L) return false
i += 6
}
return true
}
5. 黄金比例计算
val ratios = mutableListOf<Double>()
for (i in 1 until fibonacci.size) {
if (fibonacci[i - 1] != 0L) {
val ratio = fibonacci[i].toDouble() / fibonacci[i - 1].toDouble()
ratios.add(ratio)
}
}
val avgRatio = if (ratios.isNotEmpty()) ratios.sum() / ratios.size else 0.0
6. 增长率计算
val growthRates = mutableListOf<Double>()
for (i in 1 until fibonacci.size) {
if (fibonacci[i - 1] != 0L) {
val rate = ((fibonacci[i] - fibonacci[i - 1]).toDouble() / fibonacci[i - 1]) * 100
growthRates.add(rate)
}
}
val avgGrowthRate = if (growthRates.isNotEmpty()) growthRates.sum() / growthRates.size else 0.0
实战案例
案例:完整的斐波那契数列计算器
Kotlin 源代码
@OptIn(ExperimentalJsExport::class)
@JsExport
fun fibonacciCalculator(inputNumber: String = "10"): String {
// 解析输入
val n = inputNumber.trim().toIntOrNull() ?: 10
if (n < 0) {
return "❌ 错误: 输入必须是非负整数\n请输入 0 或更大的数字"
}
if (n > 50) {
return "❌ 错误: 输入过大\n为了性能考虑,请输入不超过 50 的数字"
}
// 1. 生成斐波那契数列
val fibonacci = mutableListOf<Long>()
if (n >= 1) fibonacci.add(0)
if (n >= 2) fibonacci.add(1)
for (i in 2 until n) {
fibonacci.add(fibonacci[i - 1] + fibonacci[i - 2])
}
// 2. 计算统计信息
val sum = fibonacci.sum()
val average = if (fibonacci.isNotEmpty()) sum / fibonacci.size else 0L
val max = fibonacci.maxOrNull() ?: 0L
val min = fibonacci.minOrNull() ?: 0L
// 3. 分析数列性质
val isEven = fibonacci.count { it % 2L == 0L }
val isOdd = fibonacci.count { it % 2L != 0L }
// 4. 计算相邻比率(黄金比例)
val ratios = mutableListOf<Double>()
for (i in 1 until fibonacci.size) {
if (fibonacci[i - 1] != 0L) {
val ratio = fibonacci[i].toDouble() / fibonacci[i - 1].toDouble()
ratios.add(ratio)
}
}
val avgRatio = if (ratios.isNotEmpty()) ratios.sum() / ratios.size else 0.0
// 5. 找出特殊数字
val primeNumbers = mutableListOf<Long>()
for (num in fibonacci) {
if (isPrime(num)) {
primeNumbers.add(num)
}
}
// 6. 计算增长率
val growthRates = mutableListOf<Double>()
for (i in 1 until fibonacci.size) {
if (fibonacci[i - 1] != 0L) {
val rate = ((fibonacci[i] - fibonacci[i - 1]).toDouble() / fibonacci[i - 1]) * 100
growthRates.add(rate)
}
}
val avgGrowthRate = if (growthRates.isNotEmpty()) growthRates.sum() / growthRates.size else 0.0
// 7. 数列显示
val fibonacciStr = fibonacci.joinToString(", ")
// 8. 质数列表
val primeStr = if (primeNumbers.isNotEmpty()) {
primeNumbers.joinToString(", ")
} else {
"无"
}
// 9. 比率列表(取前5个)
val ratioStr = ratios.take(5).mapIndexed { index, ratio ->
" ${index + 1}. F(${index + 2})/F(${index + 1}) = $ratio"
}.joinToString("\n")
return "🔢 斐波那契数列计算器\n" +
"━━━━━━━━━━━━━━━━━━━━━\n" +
"1️⃣ 数列信息:\n" +
" 项数: $n\n" +
" 数列: $fibonacciStr\n\n" +
"2️⃣ 基础统计:\n" +
" 总和: $sum\n" +
" 平均值: $average\n" +
" 最大值: $max\n" +
" 最小值: $min\n\n" +
"3️⃣ 奇偶分析:\n" +
" 偶数个数: $isEven\n" +
" 奇数个数: $isOdd\n\n" +
"4️⃣ 质数分析:\n" +
" 质数个数: ${primeNumbers.size}\n" +
" 质数列表: $primeStr\n\n" +
"5️⃣ 黄金比例分析:\n" +
" 平均比率: $avgRatio\n" +
" 理论值: 1.618034\n" +
" 比率列表:\n" +
ratioStr + "\n\n" +
"6️⃣ 增长率分析:\n" +
" 平均增长率: $avgGrowthRate%\n\n" +
"━━━━━━━━━━━━━━━━━━━━━\n" +
"✅ 计算完成!"
}
fun isPrime(n: Long): Boolean {
if (n <= 1) return false
if (n <= 3) return true
if (n % 2 == 0L || n % 3 == 0L) return false
var i = 5L
while (i * i <= n) {
if (n % i == 0L || n % (i + 2) == 0L) return false
i += 6
}
return true
}
ArkTS 调用代码(带输入框)
import { fibonacciCalculator } from './hellokjs';
@Entry
@Component
struct Index {
@State message: string = '加载中...';
@State results: string[] = [];
@State caseTitle: string = '斐波那契数列计算器';
@State inputText: string = '10';
aboutToAppear(): void {
this.loadResults();
}
loadResults(): void {
try {
const results: string[] = [];
const algorithmResult = fibonacciCalculator(this.inputText);
results.push(algorithmResult);
this.results = results;
this.message = '✓ 计算完成';
} catch (error) {
this.message = `✗ 错误: ${error}`;
}
}
build() {
Column() {
// 顶部标题栏
Row() {
Text('KMP 鸿蒙跨端')
.fontSize(16)
.fontWeight(FontWeight.Bold)
.fontColor(Color.White)
Spacer()
Text('Kotlin 案例')
.fontSize(14)
.fontColor(Color.White)
}
.width('100%')
.height(50)
.backgroundColor('#3b82f6')
.padding({ left: 20, right: 20 })
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.SpaceBetween)
// 案例标题
Column() {
Text(this.caseTitle)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#1f2937')
Text(this.message)
.fontSize(13)
.fontColor('#6b7280')
.margin({ top: 5 })
}
.width('100%')
.padding({ left: 20, right: 20, top: 20, bottom: 15 })
.alignItems(HorizontalAlign.Start)
// 输入框区域
Column() {
Text('输入项数 (1-50):')
.fontSize(14)
.fontWeight(FontWeight.Bold)
.fontColor('#1f2937')
.margin({ bottom: 8 })
TextInput({ placeholder: '输入斐波那契数列的项数...', text: this.inputText })
.width('100%')
.height(60)
.padding(12)
.border({ width: 1, color: '#d1d5db' })
.borderRadius(6)
.onChange((value: string) => {
this.inputText = value
})
Button('计算')
.width('100%')
.height(40)
.margin({ top: 12 })
.backgroundColor('#3b82f6')
.fontColor(Color.White)
.onClick(() => {
this.loadResults()
})
}
.width('100%')
.padding({ left: 16, right: 16, bottom: 16 })
// 结果显示区域
Scroll() {
Column() {
ForEach(this.results, (result: string) => {
Column() {
Text(result)
.fontSize(13)
.fontFamily('monospace')
.fontColor('#374151')
.width('100%')
.margin({ top: 10 })
}
.width('100%')
.padding(16)
.backgroundColor(Color.White)
.border({ width: 1, color: '#e5e7eb' })
.borderRadius(8)
.margin({ bottom: 12 })
})
}
.width('100%')
.padding({ left: 16, right: 16 })
}
.layoutWeight(1)
.width('100%')
// 底部按钮区域
Row() {
Button('示例 (10)')
.width('48%')
.height(44)
.backgroundColor('#10b981')
.fontColor(Color.White)
.fontSize(14)
.onClick(() => {
this.inputText = '10'
this.loadResults()
})
Button('清空')
.width('48%')
.height(44)
.backgroundColor('#6b7280')
.fontColor(Color.White)
.fontSize(14)
.onClick(() => {
this.inputText = ''
this.results = []
})
}
.width('100%')
.padding({ left: 16, right: 16, bottom: 20 })
}
.width('100%')
.height('100%')
.backgroundColor('#f9fafb')
}
}
编译过程详解
Kotlin 到 JavaScript 的转换
| Kotlin 特性 | JavaScript 等价物 |
|---|---|
| mutableListOf | 数组 [] |
| sum() | reduce 或循环求和 |
| count() | filter().length |
| maxOrNull/minOrNull | Math.max/min |
| toDouble() | 类型转换 |
| joinToString() | join() |
关键转换点
- 集合操作:转换为 JavaScript 数组操作
- 数学计算:转换为 JavaScript 数学运算
- 条件计数:转换为循环计数
- 字符串格式化:转换为模板字符串
工具扩展
扩展 1:添加卢卡斯数列
fun lucasSequence(n: Int): List<Long> {
val lucas = mutableListOf<Long>()
if (n >= 1) lucas.add(2)
if (n >= 2) lucas.add(1)
for (i in 2 until n) {
lucas.add(lucas[i - 1] + lucas[i - 2])
}
return lucas
}
扩展 2:添加比布那奇数列
fun tribonacci(n: Int): List<Long> {
val trib = mutableListOf<Long>()
if (n >= 1) trib.add(0)
if (n >= 2) trib.add(0)
if (n >= 3) trib.add(1)
for (i in 3 until n) {
trib.add(trib[i - 1] + trib[i - 2] + trib[i - 3])
}
return trib
}
扩展 3:添加斐波那契数列的性质检查
fun isFibonacciNumber(num: Long): Boolean {
var a = 0L
var b = 1L
while (a < num) {
val temp = a + b
a = b
b = temp
}
return a == num
}
扩展 4:添加斐波那契数列的应用
fun fibonacciGCD(n: Int, m: Int): Long {
// GCD(F(n), F(m)) = F(GCD(n, m))
val fib = mutableListOf<Long>()
// ... 生成斐波那契数列
return fib[gcd(n, m)]
}
最佳实践
1. 使用 Long 而不是 Int
// ✅ 好:使用 Long 处理大数字
val fibonacci = mutableListOf<Long>()
// ❌ 不好:Int 会溢出
val fibonacci = mutableListOf<Int>()
2. 检查边界条件
// ✅ 好:检查输入范围
if (n < 0 || n > 50) {
return "错误: 输入超出范围"
}
// ❌ 不好:不检查边界
val fib = generateFibonacci(n)
3. 避免重复计算
// ✅ 好:缓存计算结果
val fibonacci = mutableListOf<Long>()
for (i in 2 until n) {
fibonacci.add(fibonacci[i - 1] + fibonacci[i - 2])
}
// ❌ 不好:递归重复计算
fun fib(n: Int): Long {
return if (n <= 1) n.toLong() else fib(n - 1) + fib(n - 2)
}
4. 使用合适的数据结构
// ✅ 好:使用 List 存储数列
val fibonacci: List<Long> = generateFibonacci(n)
// ❌ 不好:使用数组导致大小固定
val fibonacci = LongArray(n)
5. 处理特殊情况
// ✅ 好:处理零除
if (fibonacci[i - 1] != 0L) {
val ratio = fibonacci[i].toDouble() / fibonacci[i - 1].toDouble()
}
// ❌ 不好:不检查零
val ratio = fibonacci[i].toDouble() / fibonacci[i - 1].toDouble()
常见问题
Q1: 为什么使用 Long 而不是 Int?
A: 斐波那契数列增长非常快。第 50 项已经超过 Int 的最大值 (2^31 - 1)。使用 Long 可以支持更大的项数。
// F(50) = 12586269025,超过 Int.MAX_VALUE (2147483647)
Q2: 如何优化性能?
A: 使用迭代而不是递归,避免重复计算:
// ✅ 高效:O(n) 时间复杂度
for (i in 2 until n) {
fibonacci.add(fibonacci[i - 1] + fibonacci[i - 2])
}
// ❌ 低效:O(2^n) 时间复杂度
fun fib(n: Int): Long = if (n <= 1) n.toLong() else fib(n - 1) + fib(n - 2)
Q3: 黄金比例为什么接近 1.618?
A: 这是斐波那契数列的数学性质。相邻项的比率随着项数增加而逐渐接近黄金比例 φ = (1 + √5) / 2 ≈ 1.618034。
Q4: 如何检查一个数是否是斐波那契数?
A: 一个数是斐波那契数当且仅当 5n² + 4 或 5n² - 4 是完全平方数:
fun isFibonacciNumber(num: Long): Boolean {
fun isPerfectSquare(x: Long): Boolean {
val sqrt = kotlin.math.sqrt(x.toDouble()).toLong()
return sqrt * sqrt == x
}
return isPerfectSquare(5 * num * num + 4) ||
isPerfectSquare(5 * num * num - 4)
}
Q5: 如何处理非常大的项数?
A: 对于超过 50 项,需要使用 BigInteger:
import java.math.BigInteger
fun fibonacciBig(n: Int): List<BigInteger> {
val fib = mutableListOf<BigInteger>()
if (n >= 1) fib.add(BigInteger.ZERO)
if (n >= 2) fib.add(BigInteger.ONE)
for (i in 2 until n) {
fib.add(fib[i - 1] + fib[i - 2])
}
return fib
}
总结
关键要点
- ✅ 使用 Long 处理大数字
- ✅ 使用迭代而不是递归
- ✅ 检查边界条件和特殊情况
- ✅ 利用斐波那契数列的数学性质
- ✅ KMP 能无缝编译到 JavaScript
下一步
- 实现其他数列 (卢卡斯、比布那奇等)
- 添加更多数学分析
- 实现斐波那契数列的应用
- 优化大数字处理
- 添加可视化功能
参考资源
更多推荐


所有评论(0)