用高斯公式优化 Swift 代码,让运行速度飞跃数十万倍!

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

在开发过程中,我们始终在寻找优化代码的方法。有的时候,最强大的优化来自于看似简单的方法。

今天我们探索一个 19 世纪数学家的故事------卡尔·弗里德里希·高斯(Carl Friedrich Gauss),以及如何通过他的一个简单的算术公式显著提升 Swift 算法的性能。

高斯公式的魅力

我们先提一个需求:假设你需要计算从 1 到 n 的所有整数之和。

这是一个经典问题,并且有多种解决方法。为了演示,我编写了三个 Swift 函数来完成这一任务:

  1. For-In 循环

这是最直接的方法。通过迭代每个数字并累加,得到结果。

kotlin 复制代码
func sumUsingForIn(n: Int) -> Int {
    var sum = 0
    for i in 1...n {
        sum += i
    }
    return sum
}
  1. Reduce 方法

Swift 的函数式编程特性允许我们使用 reduce 方法来对范围内的数字求和。

kotlin 复制代码
func sumUsingReduce(n: Int) -> Int {
    return (1...n).reduce(0, +)
}
  1. 高斯公式

终于到了我们的重头戏------高斯公式

年少的高斯聪明地发现从 1 到 n 的总和可以通过一个简单的等式来计算。在 Swift 中,这可以用如下方式表达:

kotlin 复制代码
func sumUsingGauss(n: Int) -> Int {
    return n * (n + 1) / 2
}

即:

性能测试

为了测量这些方法的速度,我使用了 Swift 的 DispatchTime API来记录 n 为 1,000,000 时的执行时间(单位:毫秒)。

vbscript 复制代码
import Foundation

func measureExecutionTime(for function: (Int) -> Int, with n: Int) {
    let start = DispatchTime.now()
    _ = function(n)
    let end = DispatchTime.now()
    let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
    let timeInterval = Double(nanoTime) / 1_000_000// 转换为毫秒
    print("Execution time: \(timeInterval) ms")
}

// 测试每个函数
measureExecutionTime(for: sumUsingForIn, with: 1_000_000)
measureExecutionTime(for: sumUsingReduce, with: 1_000_000)
measureExecutionTime(for: sumUsingGauss, with: 1_000_000)

大家可以自行运行上面的代码,看看结果。我这里的结果为:

yaml 复制代码
Execution time: 2976.284459 ms
Execution time: 168.619834 ms
Execution time: 0.019208 ms

谁是最快的?

在进入性能对比之前,我们需要了解一下 Big-O表示法 ------这一计算机科学的基本概念帮助我们评估算法的效率。

Big-O表示法描述了算法执行时间(或空间占用)如何随着输入规模的变化而增长。它以_n_为单位表示,其中_n_代表输入数据的大小。

例如:

  • O(1): 常数时间,算法性能与_n_无关。

  • O(n): 线性时间,执行时间随_n_线性增长。

  • O(n²): 平方时间,执行时间随_n_成平方增长。

理解 Big-O 至关重要,因为它帮助我们预测算法在输入规模扩大时的表现,从而更容易地为给定问题选择最有效的解决方案。

回到我们的对比,三种方法的 Big-O 分析如下:

  • For-In 循环 :每个数字都被单独处理,因此时间复杂度为O(n)。对于大的_n_,执行时间线性增长。

  • Reduce 方法 :尽管使用了函数式编程,但内部同样要遍历范围,复杂度同为O(n)

  • 高斯公式 :绝对的赢家。凭借其常数时间复杂度O(1),无论_n_的大小,它都能直接通过单个算术操作计算总和。

对于 n 为 1,000,000 的情况,这种差别显而易见。For-In 循环最慢,Reduce 方法在 swift 内部应该是被优化过的,而高斯公式只需 0.02 毫秒。

通过采用更聪明的算法,我们不仅可以实现更好的性能,还能提升可扩展性,使得高斯公式成为求和序列或类似问题的理想解决方案。

通过高斯公式,函数运行速度提升了几十万倍。

在实际应用中使用

让我们从理论转向实践,其实如果你注意观察,代码中很多场景适合使用高斯公式。

比如一个游戏应用,玩家在通过关卡时累积得分。为了显示排行榜,需要计算直到某一关卡 n 的总得分。

如下是我用于解决此问题的三种方法:

  1. 循环实现(基础方法)

通过迭代累加得分。

swift 复制代码
func cumulativeScoreLoop(scores: [Int], upto level: Int) -> Int {
    var total = 0
    for i in 0..<min(level, scores.count) {
        total += scores[i]
    }
    return total
}
  1. Reduce实现(函数式方法)

使用Swift的 reduce 进行求和。

swift 复制代码
func cumulativeScoreReduce(scores: [Int], upto level: Int) -> Int {
    return scores.prefix(level).reduce(0, +)
}
  1. 高斯公式实现(优化方法)

如果得分可以预测(如1, 2, 3, ...),我们可以直接计算总得分。

swift 复制代码
func cumulativeScoreGaussFormula(upto level: Int) -> Int {
    return (level * (level + 1)) / 2
}

结论

高斯公式的故事提醒我们,优化不一定要复杂。通过简单的数学原理,我们可以显著提升代码性能。希望这个故事能激励你在日常编程中寻找类似的优化机会。

欢迎在评论区分享你的看法或提出问题,让我们共同探索更多优化应用的可能性!

这里每天分享一个 iOS 的新知识,快来关注我吧

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
丿Wayne25 分钟前
iOS Token 刷新实战(Actor 避免并发重复刷新)
ios·swift·token·actor·swift并发
终端安全笔记20 小时前
iOS 27 给了租赁一个新工具,但它只认受监督的设备
android·网络·安全·ios
大熊猫侯佩21 小时前
独立 App 首发完成 iPhone Duo 展开态适配
ios·swiftui·swift
光影少年21 小时前
setImmediate 和 setTimeout(0) 的区别
android·前端·react.js·ios·前端框架
2501_916008891 天前
SSE 和 gRPC 流式接口如何抓包,调试 SSE 与 gRPC 流式接口
网络协议·计算机网络·网络安全·ios·adb·https·udp
HouWan2 天前
Flutter: MediaQuery.of(context) 为什么可能拖慢页面?
android·flutter·ios
SoaringHeart2 天前
Swift 进阶&封装:仿 Get 给SwiftUI 添加路由导航能力
swiftui·swift
用户38034165882972 天前
Broadcast Extension 里的 Live Activity:一次跨进程妥协
ios·音视频开发
匠测AI说2 天前
XCUITest 自动化全解:同进程白盒、XCTest 架构、自动同步机制与 iOS 端选型指南
测试工具·ios·自动化
silianpan2 天前
CAD 文档预览 UTS 插件
android·ios·harmonyos