PR

【Excel VBA】3変数関数の線形補間を行うExcelマクロ

3変数関数の線形補間を行うExcelマクロについて説明する。

スポンサーリンク

はじめに

\(f=f\left(x,y,z\right)\)となるような関数において、下の図のように離散的な\(\left(x,y,z\right)\)に対して\(f\)が与えられたとき、任意の\(f\left(x,y,z\right)\)の値を線形補完するExcelマクロについて紹介する。

ソースコード

ソースコードはこれ

Interpolation1DをもとにInterpolation2Dを作成し、Interpolation2DをもとにInterpolation3Dを作成しているので、3つともモジュールの中にコピペする必要がある

また、既知のx,y,zの範囲外の場合は範囲の上下限値で一定値外挿を行うようにしている。

Function Interpolation3D(ByVal x As Double, ByVal y As Double, ByVal z As Double, ParamArray ranges() As Variant) As Double

    Dim z1, z2 As Double
    Dim z1_index, z2_index As Long
    Dim nz As Long
    Dim f1, f2, f As Double
    
    'Get reference values of z and its index
    nz = (UBound(ranges, 1) + 1) / 4 - 1
    For i = 0 To nz - 1
        If ranges(4 * i + 2) <= z And ranges(4 * (i + 1) + 2) >= z Then
            z1_index = i
            z2_index = i + 1
            z1 = ranges(4 * z1_index + 2)
            z2 = ranges(4 * z2_index + 2)
        End If
    Next i
    'Constant value extrapolation in out of range of known values
    If z <= ranges(4 * 0 + 2) Then z1_index = 0
    If z >= ranges(4 * nz + 2) Then z1_index = nz - 1
    
    'Get interpolated values against x and y
    f1 = Interpolation2D(x, y, ranges(4 * z1_index + 0), ranges(4 * z1_index + 1), ranges(4 * z1_index + 3))
    f2 = Interpolation2D(x, y, ranges(4 * z2_index + 0), ranges(4 * z2_index + 1), ranges(4 * z2_index + 3))
    
    'Get interpolated values against z
    If z <= ranges(2) Then
        f = f1
    ElseIf z >= ranges(4 * nz + 2) Then
        f = f2
    Else
        f = f1 + (f2 - f1) / (z2 - z1) * (z - z1)
    End If

    Interpolation3D = f

End Function
Function Interpolation2D(ByVal x As Double, ByVal y As Double, ByRef x_range As Variant, ByRef y_range As Variant, ByRef f_range As Variant) As Double
    
    '1:lower, 2:upper
    Dim y1, y2 As Double 'reference value both sides of y
    Dim y1_index, y2_index As Long 'reference value index both sides of y
    Dim f1, f2, f As Double 'interpolated value
    Dim tmp() As Variant
    Dim i As Long
    
    ' Get reference value index of y
    With WorksheetFunction
    
        If y < .Min(y_range) Then y = .Min(y_range)     'Constant value extrapolation in range under lower limit
        y1_index = .Match(y, y_range, 1)
        y2_index = .Min(y1_index + 1, y_range.Count)    'Constant value extrapolation in range over the upper limit
        
    End With 'if x or y out of known value range, 1 and 2 indexes become same value
    
    ' Get reference values of y
    y1 = y_range(y1_index)
    y2 = y_range(y2_index)
    
    ' Get reference values of f
    f1 = Interpolation1D(x, x_range, f_range(y1_index))
    f2 = Interpolation1D(x, x_range, f_range(y2_index))

    'Get interpolated values against y
    If y2 <> y1 Then
        f = f1 + (f2 - f1) * (y - y1) / (y2 - y1)
    Else
        f = f1
    End If

    Interpolation2D = f    

End Function
Function Interpolation1D(ByVal x As Double, ByRef x_range As Variant, ByRef f_range As Variant) As Double
    
    '1:lower, 2:upper
    Dim x1, x2 As Double 'reference value both sides of x
    Dim x1_index, x2_index As Long 'reference value index both sides of x
    Dim f, f1, f2 As Double 'interpolated value
    Dim tmp() As Variant
    Dim i As Long
    
    ' Get reference value index of x
    With WorksheetFunction
        
        If x < .Min(x_range) Then x = .Min(x_range)     'Constant value extrapolation in range under lower limit
        x1_index = .Match(x, x_range, 1)
        x2_index = .Min(x1_index + 1, x_range.Count)    'Constant value extrapolation in range over the upper limit
        
    End With 'if x or y out of known value range, 1 and 2 indexes become same value
    
    ' Get reference values of x
    x1 = x_range(x1_index)
    x2 = x_range(x2_index)
    
    ' Get reference values of f
    f1 = f_range(x1_index)
    f2 = f_range(x2_index)
    
    'Get interpolated values against x
    If x2 <> x1 Then
        f = f1 + (f2 - f1) * (x - x1) / (x2 - x1)
    Else
        f = f1
    End If

    Interpolation1D = f

End Function

使い方

使い方は以下の通り

=interpolation3D(x,y,z,既知のx1,既知のy1,既知のz1,既知のf1,...)

ParamArrayを使うことで可変長引数を可能にしている。

ParamArray - Visual Basic
詳細情報: ParamArray (Visual Basic)

↓参考のマクロ付きブックはこちら

既知のx,y,zの範囲外を線形外挿したい場合は、組み込み関数であるFORECAST関数を組み合わせる必要がある。

おわりに

3変数関数の線形補間を行うExcelマクロについて説明した。

ちなみにinterpolation1Dinterpolation2Dもついでに使えるようになる。

=interpolation1D(x,既知のx1,既知のf1)
=interpolation2D(x,y,既知のx1,既知のy1,既知のf1)

↓関連記事

コメント