【问题标题】:Interpolate between array points在数组点之间插值
【发布时间】:2014-07-17 10:03:16
【问题描述】:

在以下代码中,我构建了 2 个数组:

  • 一个包含一个“度数数据”(基本上是一个递增的整数数组),表示圆周中度数的一部分。

  • 第二个是“功率数据”(一个 Double,其值或多或少地保持三次增加,直到最大值对应于第一个数组中的 0。然后它们几乎会随着增加而减少)。例如,此数组从或多或少 -4.0 到或多或少 -4.0 的值。

我认为我可以将第二个“简化”为抛物线(看起来非常像),并使用它的系数(通过 LinEst 计算)A、B、C 和 D 在之间插值数据点。

我需要的是以 0.1 度的精度找到最接近 -3.0 的 2 个数字,然后以度为单位找到它们的“距离”。 问题是:我做不到。我遗漏了一些东西,系数似乎不能代表我的数据集。

Dim i As Integer, j As Integer
Dim MaxVal As Double, MaxAngle As Integer, CyclicAngle As Double
Dim XValues() As Double, YValues() As Double, Coeff As Variant
Dim LeftAngle As Double, RightAngle As Double, LeftAngleValue As Double, RightAngleValue As Double

' Searches for the maximum value and its angle
MaxVal = -80
ReDim YValues(359 * 3 + 2)
For i = 3 To 362 ' This will fill arrays from a worksheet (defined as Public in
' another subroutine) in which the data starts from row 3. I need the data stored in
' the 2nd column)
    For j = 0 To 2 ' since the array represents a circumference, i make it "cyclic"
        YValues((i - 3) + (360 * j)) = TargetSheet.Cells(i, 2)
    Next j
    If TargetSheet.Cells(i, 2) > MaxVal Then
        MaxVal = TargetSheet.Cells(i, 2)
        MaxAngle = i - 3
    End If
Next

' The following searches the "middle" maximum
i = 0
j = 0
Do Until j = 2
    If YValues(i) = MaxVal Then
        j = j + 1
        CyclicAngle = i
    End If
    i = i + 1
Loop
' Searches in the middle for the <-3 (we name it "-4") values
i = CyclicAngle
Do Until YValues(i) < -3
    i = i + 1
Loop
RightAngle = i + 1
i = CyclicAngle
Do Until YValues(i) < -3
    i = i - 1
Loop
LeftAngle = i - 1

' Copying only the "-4" to "-4"
ReDim XValues(RightAngle - LeftAngle)
For i = 0 To RightAngle - LeftAngle
    XValues(i) = YValues(LeftAngle + i)
Next i
' Now correctly store the data in a new ordered array
ReDim YValues(UBound(XValues))
For i = 0 To UBound(XValues)
    YValues(i) = XValues(i)
    XValues(i) = LeftAngle - 360 + i
Next i

这里是批评点:

' Gets the coefficients of a 3rd degree curve representing the Y-Array
Coeff = Application.LinEst(Application.Transpose(YValues), Application.Power(Application.Transpose(XValues), Array(1, 2, 3)), True, False)

' Sets the arrays to have a point every 0.1°
LeftAngle = LeftAngle * 10
RightAngle = RightAngle * 10
MaxAngle = MaxAngle * 10
ReDim XValues(RightAngle - LeftAngle)
ReDim YValues(RightAngle - LeftAngle)
For i = LeftAngle To RightAngle
    XValues(i - LeftAngle) = i / 10
    YValues(i - LeftAngle) = Coeff(1) * (i / 10) ^ 3 + Coeff(2) * (i / 10) ^ 2 + Coeff(3) * (i / 10) + Coeff(4)
Next

现在,如果我查看 YValues 数组,其中存储的数字看起来并不完全应该是这样。 那我该如何插值来找到那些 -3 呢?

【问题讨论】:

  • 您在中间变量中继续查找“预期值”到哪一行?因为在不熟悉具体问题的情况下浏览整个代码看起来有点费时
  • 好吧,我没有找到预期值,因为大部分代码都是为了让我们了解数组是如何填充的。最后,我找到了 3 级 LinEst 系数,但从那里开始......成为龙
  • 你的 Leftangle,rightangle 变量是双精度的。使用双精度和索引运行循环不是一个好主意,使用双精度来提供数组大小当然不是一个好主意。将完成隐式转换,但我更愿意在顶部使用 Option Explicit 并使用正确的数据类型。注册。具体问题,一旦类型设置正确(最好创建一个新变量为Long 循环并初始化,保持角度为双)
  • 这可能不会有帮助:它们是 Double 因为我认为我可以使用它们来存储 exact 角度(对应于 -3 和 0.1 的值°分辨率)。提供了数组大小(如果您正在谈论ReDims),因为我只想选择圆周的一部分。对于 LeftAngle/RightAngle 骑行,你是完全正确的......
  • 是的,因此您将它们保持为双精度并使用长迭代器

标签: arrays vba excel interpolation


【解决方案1】:

错误出现在这段代码中:我认为我不能“旋转” XValues 数组

' Now correctly store the data in a new ordered array
ReDim YValues(UBound(XValues))
For i = 0 To UBound(XValues)
    YValues(i) = XValues(i)
    XValues(i) = LeftAngle + i ' Was LeftAngle - 360 + i
Next i

我现在应该能够通过简单的循环迭代找到我的 -3.0。 当然有一些障碍,但由于我有 LeftAngle 和 RightAngle 引用,我应该能够解决所有问题。

完整解决方案

请查看我的问题并使用上面的代码进行更正。从“批评点”来看:

' 获取表示 Y 数组的 3 度曲线的系数 ' 并构建一个插值数组,其点为每 0.1° Coeff = Application.LinEst(Application.Transpose(YValues), Application.Power(Application.Transpose(XValues), Array(1, 2, 3)), True, False) 'TargetSheet.Range("E1:H1") = 系数

' Sets the arrays to be every 0.1°
LeftAngle = LeftAngle * 10
RightAngle = RightAngle * 10
j = CInt(LeftAngle)
k = CInt(RightAngle)
ReDim XValues(k - j)
ReDim YValues(k - j)
For i = j To k
    XValues(i - LeftAngle) = i / 10
    YValues(i - LeftAngle) = Coeff(1) * (i / 10) ^ 3 + Coeff(2) * (i / 10) ^ 2 + Coeff(3) * (i / 10) + Coeff(4)
Next
' Now searches for the -3dB angles with a better resolution
RightAngleValue = 10
LeftAngleValue = 10
CyclicAngle = CyclicAngle * 10
i = 0
Do Until XValues(i) > CyclicAngle / 10
    If Abs(YValues(i) +3) < LeftAngleValue Then
        LeftAngleValue = Abs(YValues(i) + 3)
        LeftAngle = i * 0.1
    End If
    i = i + 1
Loop
Do Until i > UBound(XValues)
    If Abs(YValues(i) +3) < RightAngleValue Then
        RightAngleValue = Abs(YValues(i) + 3)
        RightAngle = i * 0.1
    End If
    i = i + 1
Loop
myFunction = RightAngle - LeftAngle

【讨论】:

    猜你喜欢
    • 2020-03-29
    • 2021-08-04
    • 1970-01-01
    • 2022-12-10
    • 2023-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-24
    相关资源
    最近更新 更多