You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Visual Basic .NET中List元素快速计算:正弦波峰值查找优化

正弦电压波峰值(最大值/最小值)及索引的高效查找方案

原代码的性能瓶颈分析

  1. 索引查找错误+低效:list_values_voltage.IndexOf(list_values_voltage.Item(k*Range))会遍历整个列表找匹配值,若存在重复电压值,会返回第一个匹配项的索引,导致切片范围完全错误;且每次IndexOf都是O(n)操作,循环累积后时间复杂度飙升至O(n²)。
  2. 切片逻辑错误:GetRange的长度参数用k*Range + Range会导致每次切片长度翻倍(第一次取Range个元素,第二次取2Range...),完全违背按固定周期分段的需求。
  3. 不必要的内存开销:每次GetRange都会创建新的List实例,频繁的内存分配和GC回收会大幅拖慢运行速度。

优化方案(基于已知周期的最优实现)

既然已知正弦波的输出频率,我们可以直接按固定周期区间遍历原列表,在每个区间内直接查找最大值、最小值及其索引,全程无需创建子列表,时间复杂度降至O(n):

Public Sub Leakage_Current_Result_Verification(list_current As List(Of Double), list_voltage As List(Of Double))
    ' 复用传入的列表,避免不必要的赋值
    Dim sample_rate As Double = 1000
    Dim periodTime As Double = 1 / AmetekNew.Output_Frequency
    Dim range As Integer = Convert.ToInt32(periodTime * sample_rate)
    Dim totalPeriods As Integer = list_voltage.Count \ range ' 整数除法,避免浮点运算误差

    ' 结果存储列表
    Dim list_voltage_peaks_max As New List(Of Double)
    Dim list_voltage_peaks_min As New List(Of Double)
    Dim list_voltage_peak_max_indexes As New List(Of Integer)
    Dim list_voltage_peak_min_indexes As New List(Of Integer)
    Dim list_current_at_peaks As New List(Of Double)
    Dim list_current_fault_values As New List(Of Double)
    Dim list_fault_indexes As New List(Of Integer)

    For periodIdx As Integer = 0 To totalPeriods - 1
        Dim startIdx As Integer = periodIdx * range
        Dim endIdx As Integer = startIdx + range - 1 ' 闭区间,避免越界
        ' 处理最后一段可能不足一个周期的情况
        If endIdx >= list_voltage.Count Then
            endIdx = list_voltage.Count - 1
        End If

        ' 遍历当前周期区间,找最大、最小值及对应索引
        Dim currentMax As Double = Double.MinValue
        Dim currentMin As Double = Double.MaxValue
        Dim maxIdx As Integer = startIdx
        Dim minIdx As Integer = startIdx

        For i As Integer = startIdx To endIdx
            ' 更新最大值
            If list_voltage(i) > currentMax Then
                currentMax = list_voltage(i)
                maxIdx = i
            End If
            ' 更新最小值
            If list_voltage(i) < currentMin Then
                currentMin = list_voltage(i)
                minIdx = i
            End If
            ' 同时检查电流故障(>1mA)
            If list_current(i) > 0.001 Then ' 1mA = 0.001A
                list_current_fault_values.Add(list_current(i))
                list_fault_indexes.Add(i)
            End If
        Next

        ' 存储当前周期的峰值数据
        list_voltage_peaks_max.Add(currentMax)
        list_voltage_peaks_min.Add(currentMin)
        list_voltage_peak_max_indexes.Add(maxIdx)
        list_voltage_peak_min_indexes.Add(minIdx)
        ' 存储最大值对应的电流值
        list_current_at_peaks.Add(list_current(maxIdx))
    Next
End Sub

优化点说明

  • 直接区间遍历:跳过所有子列表创建和索引查找操作,直接在原列表的周期区间内遍历,时间复杂度从O(n²)降到O(n)。
  • 避免内存浪费:全程复用原列表,无额外List实例创建,减少GC压力。
  • 逻辑修正:用整数除法计算周期数,避免浮点运算误差;处理最后一段不足一个周期的边界情况。
  • 合并操作:将电流故障检查合并到峰值查找的遍历中,避免二次遍历列表。

通用峰值检测方案(适用于周期未知/波动的场景)

如果正弦波存在频率漂移或周期未知,可采用差分法检测峰值(当前值大于左右相邻值即为局部最大值,小于则为局部最小值),同样是O(n)时间复杂度:

' 示例:查找所有局部最大值的索引
Dim peakIndexes As New List(Of Integer)
For i As Integer = 1 To list_voltage.Count - 2
    If list_voltage(i) > list_voltage(i-1) AndAlso list_voltage(i) > list_voltage(i+1) Then
        peakIndexes.Add(i)
    End If
Next

注:该方法会检测所有局部峰值,若正弦波无噪声,每个周期只会有一个最大值和一个最小值;若存在噪声,可增加滑动窗口滤波后再检测。

内容的提问来源于stack exchange,提问作者meddlrainerwiggsler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 22:35:04