Processing Ajax...

Title

Message

Confirm

Confirm

Confirm

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure you want to delete this item?

Confirm

Are you sure?

Calculate Math Equation According to BEDMAS

Description
This macro will take a copied math equation and calculate the answer in BEDMAS order.
Language
C#.net
Minimum Version
Created By
qi yang85003
Contributors
-
Date Created
Aug 8, 2024
Date Last Modified
Aug 8, 2024

Macro Code

Imports System
Imports System.Collections.Generic
Imports Microsoft.VisualBasic
Imports System.Collections
Imports System.Text.RegularExpressions
 
' The 'text' parameter will contain the text from the:
'   - Current Clipboard when run by HotKey
'   - History Item when run from the History Menu
' The returned String will be:
'   - Placed directly on the Clipboard
'   - Ignored by ClipboardFusion if it is 'Nothing'
Public Class ClipboardFusionHelper
 
    Public Shared Function ProcessText(text As String) As String
		Dim pattern As String = "\[[^\[\]]*\]"
      	Dim replacement As String = ""
      	Dim rgx As Regex = New Regex(pattern)
      	Dim result As String = rgx.Replace(text, replacement)
		Return calculateValue(result)
	End Function
	
	Public Shared Function calculateValue(text As String) As String
		Dim pattern As String = "[0-9\.+-/*()()= ]+"
		Dim rgx As Regex = New Regex(pattern)
		Dim match As Boolean = rgx.IsMatch(text)
		Dim mt As MatchCollection = rgx.Matches(text)
		If(Not match) Then
			Return "The expression contains illegal characters!"
		End If

         
        Dim count As Integer = 0
        For Each m In mt
            count= count+1
        Next m
        If(count>1) Then
            Return "The expression contains illegal characters!"
        End If
         
        Dim opt_stk As Stack = New Stack()
        Dim num_stk As Stack = New Stack()
        Dim sb_temp As String = ""
 
        Dim items = text.ToCharArray
        For i = 0 To text.Length-1
            Dim c = items(i)
            If (c <> " ") Then
                If ((c >= "0" And c <= "9") Or c = "." Or (c="-" And sb_temp.Length =0)) Then
                    sb_temp = sb_temp + c
                Else
                    If (sb_temp.Length >0) Then
                        Dim temp_value As Double
                        temp_value = sb_temp
                        num_stk.push(temp_value)
                        sb_temp = ""
                    End If
 
                    Dim curOpt As String = c
                    If (opt_stk.Count = 0) Then
                        opt_stk.Push(curOpt)
                    Else
                        If (curOpt.Equals("(")) Then
                            opt_stk.Push(curOpt)
                        ElseIf (curOpt.Equals(")")) Then
                            directCalc(opt_stk, num_stk, True)
                        ElseIf (curOpt.Equals("="))
                            directCalc(opt_stk, num_stk, False)
                            Return Math.Round(num_stk.Pop,3)
                        Else
                            compareAndCalc(opt_stk, num_stk, curOpt)
                        End If
                    End If
                End If
            End If
        Next
 
        If (sb_temp.Length>0) Then
            Dim temp_value As Double
            temp_value = sb_temp
            num_stk.push(temp_value)
        End If
        directCalc(opt_stk, num_stk, False)
        Return Math.Round(num_stk.Pop,3)
    End Function
 
    Public Shared Function directCalc(optStack As Stack, numStack As Stack, isBracket As Boolean)
        Dim opt As String = optStack.Pop
        Dim num2 As Double = numStack.Pop
        Dim num1 As Double = numStack.Pop
        Dim result As Double = floatingPointCalc(opt, num1, num2)
 
        numStack.Push(result)
 
        If (isBracket) Then
            If (optStack.Peek.Equals("(")) Then
                optStack.Pop
            Else
                directCalc(optStack, numStack, isBracket)
            End If
        Else
            If (optStack.Count>0) Then
                directCalc(optStack, numStack, isBracket)
            End If
        End If
    End Function
 
    Public Shared Function compareAndCalc(optStack As Stack, numStack As Stack, curOpt As String) As Double
        Dim peekOpt = optStack.Peek
        Dim priority = getPriority(peekOpt, curOpt)
        If (priority = -1 Or priority = 0) Then
            Dim opt As String = optStack.Pop
            Dim num2 As Double = numStack.Pop
            Dim num1 As Double = numStack.Pop
            Dim result As Double = floatingPointCalc(opt, num1, num2)
 
            numStack.Push(result)
 
            If (optStack.Count = 0) Then
                optStack.Push(curOpt)
            Else
                compareAndCalc(optStack, numStack, curOpt)
            End If
        Else
            optStack.Push(curOpt)
        End If
 
    End Function
 
    Public Shared Function getPriority(opt1 As String, opt2 As String) As Integer
        Dim map As SortedList = New SortedList()
        map.Add("(", 0)
        map.Add("+", 2)
        map.Add("-", 2)
        map.Add("*", 3)
        map.Add("/", 3)
        map.Add(")", 7)
        map.Add("=", 20)
        Dim index1 = map.IndexOfKey(opt1)
        Dim value1 = map.GetByIndex(index1)
        Dim index2 = map.IndexOfKey(opt2)
        Dim value2 = map.GetByIndex(index2)
        Return value2 - value1
    End Function
 
    Public Shared Function floatingPointCalc(opt As String, val1 As Double, val2 As Double) As Double
        Dim result As Double
        If (opt.Equals("+")) Then
            result = val1 + val2
        End If
        If (opt.Equals("-")) Then
            result = val1 - val2
        End If
        If (opt.Equals("*")) Then
            result = val1 * val2
        End If
        If (opt.Equals("/")) Then
            result = val1 / val2
        End If
        Return result
    End Function
 
End Class