KMP 实现鸿蒙跨端:Kotlin 斐波那契数列计算器
本文介绍了一个基于Kotlin Multiplatform的斐波那契数列计算器实现方案。该工具支持生成1-50项的斐波那契数列,并提供多维分析功能,包括基础统计(总和、平均值、极值)、奇偶分析、质数识别、黄金比例计算和增长率分析。核心算法采用高效迭代生成数列,时间复杂度为O(n),并实现了优化的质数检查算法。通过KMP技术,该工具可跨平台运行,在OpenHarmony应用中展示数学计算的魅力。案例

目录
概述
本文档介绍如何在 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])
}
这段代码实现了斐波那契数列的高效迭代生成算法。首先创建一个可变的 Long 类型列表,使用 Long 而不是 Int 是因为斐波那契数列增长极快,第 50 项已经超过 Int 的最大值。然后根据项数 n 的大小分别添加初始值:如果 n >= 1 添加 0(第一项),如果 n >= 2 添加 1(第二项)。接着使用 for 循环从第 3 项开始,每一项都是前两项的和。这个算法的时间复杂度是 O(n),空间复杂度也是 O(n),相比递归实现的 O(2^n) 时间复杂度要高效得多。
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
这段代码计算了斐波那契数列的四个基本统计量。fibonacci.sum() 直接调用 Kotlin 内置函数计算数列中所有数字的总和。对于平均值,使用条件表达式检查列表是否为空,如果非空则计算 sum / fibonacci.size,否则返回 0L。maxOrNull() 和 minOrNull() 是安全的函数,当列表为空时返回 null 而不会抛出异常,通过 Elvis 操作符 ?: 0L 提供默认值。这些统计量可以帮助我们理解数列的整体特性,例如最大值和最小值反映了数列的范围,平均值反映了数列的中心趋势。
3. 奇偶分析
val isEven = fibonacci.count { it % 2L == 0L }
val isOdd = fibonacci.count { it % 2L != 0L }
这段代码统计了斐波那契数列中的偶数和奇数个数。count() 函数遍历数列中的每个元素,并根据提供的条件进行计数。第一行使用模运算 it % 2L == 0L 判断数字是否为偶数,统计所有偶数的个数。第二行使用 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
}
这段代码实现了高效的质数检查算法。首先处理特殊情况:小于等于 1 的数不是质数,2 和 3 是质数。然后检查是否能被 2 或 3 整除,如果能则不是质数。接着使用一个优化的循环:从 5 开始,每次增加 6(即检查 5, 11, 17, 23…),这是因为所有质数(除了 2 和 3)都可以表示为 6k±1 的形式。循环条件 i * i <= n 是因为如果 n 有因子大于 √n,那么必然有对应的因子小于 √n。这个算法的时间复杂度是 O(√n),相比逐一检查所有数字要高效得多。
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
这段代码计算了斐波那契数列相邻项的比率,这是一个有趣的数学性质。首先创建一个 Double 类型的列表来存储比率。然后遍历数列,对于每一项,计算它与前一项的比率。注意检查 fibonacci[i - 1] != 0L 是为了避免除以零的错误。使用 toDouble() 进行类型转换,确保进行浮点数除法而不是整数除法。最后计算所有比率的平均值。有趣的是,随着项数增加,这个比率会逐渐接近黄金比例 φ = (1 + √5) / 2 ≈ 1.618034,这是斐波那契数列的一个著名性质,体现了数学的美妙。
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
这段代码计算了斐波那契数列的增长率,用百分比表示。增长率公式是 (当前项 - 前一项) / 前一项 * 100,这反映了数列从一项到下一项的增长幅度。首先创建一个列表存储所有的增长率。然后遍历数列,对于每一项,计算它相对于前一项的增长百分比。同样需要检查前一项是否为零以避免除以零错误。最后计算所有增长率的平均值。有趣的是,斐波那契数列的增长率也会逐渐趋于稳定,最终接近黄金比例减 1(即 φ - 1 ≈ 0.618),这反映了数列增长的加速趋势。
实战案例
案例:完整的斐波那契数列计算器
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
}
这是斐波那契数列计算器的核心实现函数。函数使用 @OptIn(ExperimentalJsExport::class) 和 @JsExport 注解,使其可以被编译成 JavaScript 并在 ArkTS 中调用。函数首先进行输入验证:使用 toIntOrNull() 安全地将字符串转换为整数,如果转换失败则使用默认值 10;检查输入是否为负数或超过 50(为了性能考虑)。然后依次执行六个主要步骤:生成斐波那契数列、计算基础统计量、分析奇偶性、计算黄金比例相关的比率、识别质数、计算增长率。最后使用字符串拼接构建格式化的输出结果,包含表情符号和分隔线,使输出更加美观易读。整个函数展示了如何综合运用 Kotlin 的各种特性来实现一个完整的数学分析工具。
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')
}
}
这段 ArkTS 代码是鸿蒙应用的用户界面实现,通过 import 语句导入之前编译的 Kotlin 函数。使用 @State 装饰器定义四个响应式状态变量:message 用于显示状态信息,results 存储计算结果,caseTitle 显示标题,inputText 存储用户输入的项数。aboutToAppear() 生命周期函数在组件加载时自动调用 loadResults() 进行初始计算。loadResults() 方法调用 Kotlin 函数并处理结果,使用 try-catch 捕获异常。build() 方法构建整个 UI 布局,分为五个部分:顶部蓝色标题栏、案例标题和状态信息、用户输入区域(包含文本输入框和计算按钮)、可滚动的结果显示区域以及底部的示例数据和清空按钮。整个界面采用响应式设计,使用 Flexbox 布局和现代化的配色方案。
编译过程详解
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 和 1(而斐波那契数列是 0 和 1),因此生成的数列是:2, 1, 3, 4, 7, 11, 18, 29…。卢卡斯数列有许多有趣的性质,例如 L(n) = F(n-1) + F(n+1),其中 F(n) 是第 n 个斐波那契数。卢卡斯数列在数论和组合数学中有重要应用。
扩展 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
}
比布那奇数列(Tribonacci)是斐波那契数列的推广,每一项是前三项的和而不是前两项的和。这个函数实现了比布那奇数列的生成,初始值是 0, 0, 1,因此生成的数列是:0, 0, 1, 1, 2, 4, 7, 13, 24…。与斐波那契数列类似,比布那奇数列也有相邻项比率趋于某个常数的性质,这个常数称为比布那奇常数,约为 1.839。比布那奇数列在某些计算机算法和组合问题中有应用。这个扩展展示了如何推广斐波那契数列的概念。
扩展 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
}
这个函数检查一个给定的数字是否是斐波那契数列中的数。实现方法是生成斐波那契数列,直到找到大于等于给定数字的项。使用两个变量 a 和 b 分别表示当前和下一个斐波那契数,初始值为 0 和 1。在循环中,使用临时变量 temp 来保存 a + b 的值,然后更新 a 和 b。当 a 等于给定的数字时,说明这个数字是斐波那契数;当 a 超过给定的数字时,说明这个数字不是斐波那契数。这个方法的时间复杂度是 O(log n),因为斐波那契数列增长指数级,所以项数相对较少。
扩展 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)]
}
这个函数展示了斐波那契数列的一个有趣的数学性质:两个斐波那契数的最大公约数等于它们索引的最大公约数对应的斐波那契数。即 GCD(F(n), F(m)) = F(GCD(n, m))。这个性质在数论中有重要应用。例如,F(12) 和 F(8) 的最大公约数等于 F(GCD(12, 8)) = F(4)。这个函数首先生成斐波那契数列,然后计算两个索引的最大公约数,最后返回对应索引的斐波那契数。这个性质可以用来快速计算斐波那契数列中两个数的最大公约数,而不需要直接计算这两个数的最大公约数。
最佳实践
1. 使用 Long 而不是 Int
// ✅ 好:使用 Long 处理大数字
val fibonacci = mutableListOf<Long>()
// ❌ 不好:Int 会溢出
val fibonacci = mutableListOf<Int>()
这个最佳实践强调了选择合适数据类型的重要性。斐波那契数列增长非常快,第 50 项已经达到 12586269025,远超 Int 的最大值 2147483647。使用 Long 可以处理更大的数字,Long 的最大值是 9223372036854775807,足以处理斐波那契数列的前 93 项。如果使用 Int,程序会在计算到第 47 项时发生整数溢出,导致错误的结果。这个教训适用于所有涉及快速增长的数列或数学计算的场景。
2. 检查边界条件
// ✅ 好:检查输入范围
if (n < 0 || n > 50) {
return "错误: 输入超出范围"
}
// ❌ 不好:不检查边界
val fib = generateFibonacci(n)
这个最佳实践强调了输入验证的重要性。在处理用户输入时,必须检查输入是否在合理的范围内。对于斐波那契数列计算器,应该检查项数是否为非负数,以及是否超过了可以处理的最大值(如 50)。不检查边界条件会导致多个问题:负数会导致不合理的结果,过大的数字会导致性能问题或整数溢出。通过提前检查并返回清晰的错误信息,可以提高用户体验,并防止程序崩溃或产生错误的结果。
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)
}
这个最佳实践强调了性能优化的重要性。使用迭代方法缓存计算结果的时间复杂度是 O(n),而简单的递归实现的时间复杂度是 O(2^n)。例如,计算第 50 个斐波那契数,迭代方法只需要 50 次操作,而递归方法需要超过 10^15 次操作,这会导致程序无法在合理的时间内完成。缓存计算结果的方法不仅大大提高了性能,而且代码也更简洁易懂。这个教训适用于所有涉及重复计算的场景,包括动态规划问题。
4. 使用合适的数据结构
// ✅ 好:使用 List 存储数列
val fibonacci: List<Long> = generateFibonacci(n)
// ❌ 不好:使用数组导致大小固定
val fibonacci = LongArray(n)
这个最佳实践强调了选择合适数据结构的重要性。使用 List(特别是 mutableListOf)比使用数组更灵活,因为 List 可以动态增长,而数组的大小是固定的。在生成斐波那契数列时,如果使用数组,需要提前知道数列的长度,这会增加代码的复杂性。使用 List 可以在生成过程中动态添加元素,代码更简洁。此外,List 提供了更多的方法和操作,如 sum()、maxOrNull()、count() 等,使得后续的数据处理更加方便。
5. 处理特殊情况
// ✅ 好:处理零除
if (fibonacci[i - 1] != 0L) {
val ratio = fibonacci[i].toDouble() / fibonacci[i - 1].toDouble()
}
// ❌ 不好:不检查零
val ratio = fibonacci[i].toDouble() / fibonacci[i - 1].toDouble()
这个最佳实践强调了处理特殊情况的重要性。在计算比率或进行其他数学运算时,必须检查分母是否为零。在斐波那契数列中,第一项是 0,所以在计算比率时,如果不检查前一项是否为零,就会导致除以零的错误。在 Kotlin 中,除以零会导致 Infinity 或 NaN,这会导致后续的计算出错。通过提前检查并跳过无效的计算,可以防止这类错误。这个教训适用于所有涉及数学运算的场景。
常见问题
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)