|
楼主 |
发表于 2019-10-23 09:22
|
显示全部楼层
本帖最后由 ggmmlol 于 2019-10-26 21:37 编辑
本次更新,包含2个方面:1、提高效率;2、对0层括号的超长计算式,优化计算过程为分段处理。理论上可计算无限长度的无括号的四则运算式。
为提高函数运算效率,再次使用模块级全局变量,减少创建Html对象的次数,为修正“当不规范的计算式造成的‘运行错误’时,自动引用上一次函数结果的Bug”,设置模块内全局变量,比较与上一次结果的异同,如果相同,则强制上一次的结果为"空",然后再次计算,如果计算结果仍为空,判定为计算式不规范。此外,为减少DDL缓存,每2^10次函数计算后,清除原对象,重建html对象。
代码多了不少,但为了效率提升,还是很值得的。
jss.rar
(42.9 KB, 下载次数: 131)
- Option Explicit
- Private oDom As Object, oWin As Object, JSCode As String, Initialized As Boolean, beCleaned As Boolean, Partitioned As Boolean
- Private tms%, oReg As Object, lastValue, lastexp$, a, b
- Sub Form_Load()
- Dim i%, tmp0$, tmp1$
- JSCode = "<script Language = JScript> function JS_EVAL(){return ExpValue}; var ExpValue; </script>"
- Set oDom = CreateObject("htmlfile")
- Set oWin = oDom.parentWindow
- oDom.write JSCode
- Set oReg = CreateObject("vbscript.regexp")
- oReg.Global = True
- tmp0 = "\blog\(、\blog10e\b、\bln(?=10\b|2\b)、+、-、×、÷、(、)、(\d*\.?\d+|\w*\([^\(\)]*\)|\w+)\^(-?\d*\.?\d+|\w*\([^\(\)]*\)|\w+)、" & _
- "\btrunc\b、\bint\b、\b(sqrt|round|random|pow(er)?|pi(\(\))?|min|max|log(10e)?|ln(2|10)|exp|e|abs|a?tan2?|a?sin|a?cos)\b、" & _
- "\[[^\[\]]*\]|【[^【】]*】|(Math\.)(?=\1)|[\f\n\r\v\t]、power\b、Math.e\b、\.pi(\(\))?、\b(Math\.)?ln\(、(-\+*-|\+)+(?=[\+\-])|[\+\-]+$、--"
- tmp1 = "log10e*log(、Math.LOG10E、Math.LN、+、-、*、/、(、)、pow($1,$2)、" & _
- "parseInt、Math.floor、Math.$1、、pow、Math.E、.PI、Math.log(、、+"
- a = Split(tmp0, "、")
- b = Split(tmp1, "、")
- lastexp = Empty
- Initialized = True
- End Sub
- Private Function EXPCLEAN(ByVal exp$) As String
- Dim i As Integer
- If Not Initialized Then Form_Load
- If Not beCleaned Then
- exp = LCase(exp)
- With oReg
- For i = 0 To UBound(a)
- .Pattern = a(i)
- exp = .Replace(exp, b(i))
- Next
- End With
- beCleaned = True
- End If
- EXPCLEAN = exp
- End Function
- Function JSEVAL(ByVal s$) As Variant
- Dim s1$, s2$, s3$
- s = EXPCLEAN(s)
- If Len(s) = 0 Then
- JSEVAL = ""
- Else
- If s = lastexp And Len(lastValue) Then JSEVAL = lastexp: Exit Function
- If tms >= 1023 Then ReSet
- If Not Partitioned Then
- oReg.Pattern = "^([\d\D]*?)(\b\w[^()]{2040,}\w\b(?!\.))[\d\D]*"
- If oReg.test(s) Then
- Partitioned = True
- oReg.Pattern = "^([\d\D]*?)(\b\w[^()]{60,2044}\w\b(?!\.))[\d\D]*"
- Do While oReg.test(s)
- s1 = oReg.Replace(s, "$1")
- s2 = oReg.Replace(s, "$2")
- s3 = Mid(s, Len(s1) + Len(s2) + 1)
- s2 = JSEVAL(oReg.Replace(s, "$2"))
- s = s1 & s2 & s3
- Loop
- Partitioned = False
- End If
- End If
- oDom.write "<script Language = JScript> ExpValue = " & s & "; </script>"
- JSEVAL = oWin.eval("JS_EVAL()")
- If JSEVAL = lastValue And IsNumeric(lastValue) Then
- oDom.write "<script Language = JScript> ExpValue = """"; </script>"
- JSEVAL = oWin.eval("JS_EVAL()")
- oDom.write "<script Language = JScript> ExpValue = " & s & "; </script>"
- JSEVAL = oWin.eval("JS_EVAL()")
- End If
- If Len(JSEVAL) = 0 Then JSEVAL = VBA.Error$(93)
- End If
- lastValue = JSEVAL: lastexp = s: beCleaned = Partitioned: tms = tms + 1
- End Function
- Sub ReSet()
- Set oWin = Nothing
- Set oDom = Nothing
- Initialized = False
- beCleaned = False
- Partitioned = False
- lastexp = Empty
- lastValue = 0
- tms = 0
- Form_Load
- End Sub
复制代码
|
|