如何在JavaScript中编写等价的;应用程序。匹配“;在VBA中用于数值插值函数
我想用JavaScript编写一个插值函数,以便能够使用GoogleSheets而不是Excel进行多种用途。在Excel中,我使用VBA编写了此用户定义函数:如何在JavaScript中编写等价的;应用程序。匹配“;在VBA中用于数值插值函数,javascript,excel,vba,match,interpolation,Javascript,Excel,Vba,Match,Interpolation,我想用JavaScript编写一个插值函数,以便能够使用GoogleSheets而不是Excel进行多种用途。在Excel中,我使用VBA编写了此用户定义函数: Function interpolate_1D(xreq As Single, x As Range, y As Range) As Single ' If we have variable y that is a function of x and have two ranges, x and y that give the val
Function interpolate_1D(xreq As Single, x As Range, y As Range) As Single
' If we have variable y that is a function of x and have two ranges, x and y that give the values
'of y for particular values of x, we may need to find the value of y for a value of x not 'given in the table.
'For example, we may have power curve data for a wind turbine that gives the power output of a wind turbine
'for integer values of the wind speed. To find the output power at any other speed we could 'use this function, using as arguments:
'xreq: wind speed for which we wish to know the output power
'x: range containing the known wind speeds in ascending order
'y: range containing the known wind turbine powers
Dim pointer As Integer
Dim x0 As Single, y0 As Single, x1 As Single, y1 As Single
pointer = Application.Match(xreq, x, 1)
x0 = x(pointer)
x1 = x(pointer + 1)
y0 = y(pointer)
y1 = y(pointer + 1)
interpolate_1D = y0 + (xreq - x0) * (y1 - y0) / (x1 - x0)
End Function
我可能是从某个地方抄来的,比如比洛为科学家和工程师写的关于Excel的书。它工作得很好,就像我写的2D版本一样
我对JavaScript相当陌生,目前还不知道如何让它执行Application.Match(xreq,x,1)行的等效操作,在该行中,它查看已知x值的范围,并找到小于搜索值xreq的最大值的位置。一旦我得到了那个职位,我就可以做任何事情
有什么想法吗?您可以使用给定的函数,在循环中添加您自己的逻辑,以找到您要查找的值。您可能不需要这样做。您可以使用数组
.IndexOf
方法:
a的结果将是:2
是否可以用另一种语言重新创建优化的Match
工作表函数需要对底层代码有更详细的了解,目前我无法提供给您
否则,在看不到更多您正在做的事情的情况下,我会说尝试重建匹配
函数--虽然它会更慢--就像在数组上进行蛮力迭代一样简单(如果在数组上而不是在范围对象上进行测试,这会更快)
在这些测试中,我修改了Contains
函数,将其传输到数组后,根据范围.Value
对其进行测试。我对数组和范围对象测试Match
函数,并对范围测试WorksheetFunction.Match
Sub Tester()
Application.ScreenUpdating = False
Dim i As Long, B, T
Dim Arr As Variant
Dim rng As Range
Set rng = Range("A1:A10000")
rng.Formula = "=""value_""&" & "RandBetween(1,1000)"
Range("A100000").Value = "Value_50"
T = Timer
Arr = Application.Transpose(rng.Value)
For i = 1 To 10000
B = Contains(Arr, "Value_50")
Next i
Debug.Print "Contains (array)" & vbTab & Timer - T
T = Timer
Arr = Application.Transpose(rng.Value)
For i = 1 To 10000
B = Application.Match("Value_50", Arr, False)
Next i
Debug.Print "Match (array)" & vbTab & Timer - T
T = Timer
For i = 1 To 10000
B = Application.Match("Value_50", rng, False)
Next i
Debug.Print "Match (range)" & vbTab & Timer - T
T = Timer
On Error Resume Next
For i = 1 To 10000
B = Application.WorksheetFunction.Match("Value_50", rng, False)
Next i
On Error GoTo 0
Debug.Print "WorksheetFunction.Match (range)" & vbTab & Timer - T
Application.ScreenUpdating = True
End Sub
观察到在内存中的数组上执行Contains
自定义函数比Match
快,但是应用程序.Match
和应用程序.WorksheetFunction.Match
函数在工作表上的范围
对象上执行时都比这两个函数快得多:
Contains (array) 18.90625
Match (array) 43.25
Match (range) 0.2304688
WorksheetFunction.Match (range) 0.1914063
感谢与@charleswillams的评论/讨论,以帮助您进行计时测试,并澄清其中的一些内容。@All
最后,我实现了这一目标:
function interpolate (xreq,knowndata){
var data = knowndata;
for (var i = 0; i < data.length-1; i++) {
if (xreq >=data[i][0] & xreq <data[i+1][0]) {break}
}
return data[i][1] + (data[i+1][1] - data[i][1]) / ( data[i+1][0] - data[i][0]) * (xreq - data[i][0]);
}
函数插值(xreq,knownda){
var数据=已知数据;
对于(变量i=0;i if(xreq>=data[i][0]&xreq-Tim-Williams方法比使用.MATCH快,如果数组已经作为VBA数组存在,因为每次调用.MATCH都会导致将数组传输到.MATCH可以处理的对象上的大量开销。如果(如上问题所述)数据是Excel范围,则使用.MATCH要快得多(避免了数据转换开销)@CharlesWilliams根据我刚刚做的一些测试,这似乎是错误的——将范围.value
传输到数组并处理内存中的数据更快。这几乎总是正确的,在这种情况下,开销最小,在内存中处理数组比访问范围对象或工作表对象更快.谢谢大家。我以前在一个范围内使用过迭代方法,发现匹配速度快得多,尽管这对于我通常使用的大多数非常小的数据集来说并不重要,而且我没有像Tim Williams那样进行仔细的测试。IndexOf方法看起来很有希望。我会玩,让你知道我走了多远。再次感谢。@David,速度取决于t数据范围的大小、使用的excel版本以及使用的搜索方法(二进制搜索或线性搜索)。对于少量数据,我没有测量时差,因为它无关紧要。@charleswillams很可能存在匹配优于迭代的情况,但目前我所质疑的是一个普遍的假设,“如果数据是Excel范围,则使用匹配要快得多”这似乎至少不是普遍正确的。
function interpolate (xreq,knowndata){
var data = knowndata;
for (var i = 0; i < data.length-1; i++) {
if (xreq >=data[i][0] & xreq <data[i+1][0]) {break}
}
return data[i][1] + (data[i+1][1] - data[i][1]) / ( data[i+1][0] - data[i][0]) * (xreq - data[i][0]);
}