Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
3 views

Excel_VBA_interpolation1

The document describes the PINTERP function, an Excel VBA macro for interpolation of data points. It supports linear and quadratic interpolation methods and includes error handling for various input conditions. The function is licensed under the GNU Lesser General Public License and was created by Eric J. Geyer.

Uploaded by

tranhuan061120
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views

Excel_VBA_interpolation1

The document describes the PINTERP function, an Excel VBA macro for interpolation of data points. It supports linear and quadratic interpolation methods and includes error handling for various input conditions. The function is licensed under the GNU Lesser General Public License and was created by Eric J. Geyer.

Uploaded by

tranhuan061120
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 3

Function PINTERP(xtab As Range, ytab As Range, x, Optional Linear)

' PINTERP Version 1.0.0: Original OpenOffice Macro


' PINTERP Version 1.0.1: Excel VBA conversion
'
' Excel VBA Spreadsheet Interpolation Macro
'
' Copyright (C) 2010, 2012 Eric J. Geyer
'
' This PINTERP function is free software: you can redistribute it
' and/or modify it under the terms of the GNU Lesser General Public
' License as published by the Free Software Foundation, either
' version 3 of the License, or (at your option) any later version.
'
' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
' GNU Lesser General Public License for more details.
'
' You should have received a copy of the GNU Lesser General Public License
' along with this program. If not, see <http://www.gnu.org/licenses/>.
'
' Eric J. Geyer
' geyerej@gmail.com
' 405 Lippershey Ct.
' Cary, NC 27513
'
' Input:
' xtab: array of n x values
' ytab: array of n y values
' x: interpolant
' Linear: optional boolean; forces linear interpolation if >0
'
' Output:
' y: interpolated y at x
'
' Interpolation method:
' n=2: linear
' n=3: quadratic
' n>3: average of two possible quadratics through nearest 4 local points
' Linear: linear if optional Linear argument is true
'
' Cubic spline not used due to spreadsheet macro run time issues.
' Calculation time is prohibitive if calls to such a macro were copied to a
' very large number of spreadsheet cells with potential for different table
' input on each call, because this would require solving the spline matrix
' for every call. A simple average of the two possible quadratics through
' the nearest 4 local points (excepting single quadratic for end intervals)
' is nearly as good (i.e., cubic for equal spaced interior points), without
' this run time penalty.
'
Dim descending As Boolean
Dim nx, lo, hi, mid, nquad As Long
Dim quad, b1, b2 As Double
Dim delhilo, dellolo1, delhilo1, delhi1hi, delhi1lo As Double
'
' Default is more accurate quadratic interpolation
' Linear interpolation is for exceptional cases only
'
If IsMissing(Linear) Then Linear = 0
'
' Check Input Data
' Avoid loop counting data as it is inefficient for large tables
'
nx = xtab.Count
If (nx < 2) Then
PINTERP = "Error: nX<2"
Exit Function
End If
'
If (nx <> ytab.Count) Then
PINTERP = "Error: nX<>nY"
Exit Function
End If
'
' Allow limited extrapolation
'
If (((xtab(1) - x) / (xtab(2) - xtab(1))) > 0.2 Or _
((x - xtab(nx)) / (xtab(nx) - xtab(nx - 1))) > 0.2) Then
PINTERP = "Error: >20% extrapolation"
Exit Function
End If
'
' Locate interval containing x with bisection
' Run time is very important for huge spreadsheet tables:
' a) Do not test for table order(via descending Xor...) inside Loop
' b) Do not check equality inside Loop
' Run time is not important at all for small tables:
' a) Accept 1 extra iteration to avoid equality check in loop
'
descending = (xtab(1) > xtab(nx))
lo = 1
hi = nx
If (descending) Then
Do While (lo < hi)
'do not use average to avoid addition overflow; note backslash integer divide
mid = lo + (hi - lo) \ 2
If (x < xtab(mid)) Then
lo = mid + 1
Else
hi = mid
End If
Loop
Else
Do While (lo < hi)
'note no averaging to prevent addition overflow; and backslash integer divide
mid = lo + (hi - lo) \ 2
If (x > xtab(mid)) Then
lo = mid + 1
Else
hi = mid
End If
Loop
End If
If (descending Xor (x > xtab(1))) Then
lo = hi - 1
Else
hi = lo + 1
End If
'
' Check for divide by zero and save result for re-use.
'
delhilo = (xtab(hi) - xtab(lo))
If (delhilo = 0) Then
PINTERP = "Error: Equal X values"
Exit Function
End If
'
' Linear for 2 points
'
If nx < 3 Or Linear Then
PINTERP = ytab(lo) + (x - xtab(lo)) / delhilo * (ytab(hi) - ytab(lo))
Exit Function
End If
'
' Compute possible Newton quadratic polynomials
'
nquad = 0
quad = 0
If lo > 1 Then
'
dellolo1 = (xtab(lo) - xtab(lo - 1))
If (dellolo1 = 0) Then
PINTERP = "Error: Equal X values"
Exit Function
End If
'
delhilo1 = (xtab(hi) - xtab(lo - 1))
If (delhilo1 = 0) Then
PINTERP = "Error: Equal X values"
Exit Function
End If
'
b1 = (ytab(lo) - ytab(lo - 1)) / dellolo1
b2 = ((ytab(hi) - ytab(lo)) / delhilo - b1) / delhilo1
quad = ytab(lo - 1) + b1 * (x - xtab(lo - 1)) + b2 * (x - xtab(lo - 1)) * (x - xtab(lo))
nquad = nquad + 1
End If
If hi < nx Then
'
delhi1hi = (xtab(hi + 1) - xtab(hi))
If (delhi1hi = 0) Then
PINTERP = "Error: Equal X values"
Exit Function
End If
'
delhi1lo = (xtab(hi + 1) - xtab(lo))
If (delhi1lo = 0) Then
PINTERP = "Error: Equal X values"
Exit Function
End If
'
b1 = (ytab(hi) - ytab(lo)) / delhilo
b2 = ((ytab(hi + 1) - ytab(hi)) / delhi1hi - b1) / delhi1lo
quad = quad + ytab(lo) + b1 * (x - xtab(lo)) + b2 * (x - xtab(lo)) * (x - xtab(hi))
nquad = nquad + 1
End If
'
PINTERP = quad / nquad
End Function

You might also like