{"id":29,"date":"2010-03-11T20:22:26","date_gmt":"2010-03-12T01:22:26","guid":{"rendered":"http:\/\/anvil-of-time.com\/2010\/03\/11\/powerbuilder-evaluating-arithmetic-expressions\/"},"modified":"2021-03-08T19:04:53","modified_gmt":"2021-03-09T00:04:53","slug":"powerbuilder-evaluating-arithmetic-expressions","status":"publish","type":"post","link":"https:\/\/anvil-of-time.com\/powerbuilder\/powerbuilder-evaluating-arithmetic-expressions\/","title":{"rendered":"Powerbuilder &#8211; Evaluating Arithmetic Expressions"},"content":{"rendered":"<p>Below is a function which allows the user to enter an arithmetic expression and then evaluate it and return the result.\u00a0 This will work for addition (+), subtraction(-), multiplication(*), division(\/), and exponentiation(^).\u00a0\u00a0 You can also enter parenthesis to change the order of precedence if needed.\u00a0 You would call this from where ever you like to validate and convert user entered expressions.<\/p>\n<p>Example:\u00a0 you need to calculate the area of a circle the user types in.\u00a0 User would type &#8220;3.14*8^2&#8221; in the case of a circle with a radius of 8.\u00a0 Function would return a string of &#8220;200.96&#8221;<\/p>\n<pre name=\"code\" class=\"VB\">public function string uf_eval_arithmetic_expression (string infix_expr, integer precision);\n\n\/\/ convert an expression into a numeric value (string in, number converted to string out)\n\/\/\ndecimal ld_result, ld_operand_stack [], ld_operand1, ld_operand2, ld_temp_result\nstring ls_infix_str, ls_currchar\nstring ls_infix_token [], ls_operator_stack [], ls_postfix_token [], ls_token\ninteger li_stack_top, li_itoken_sub, li_ptoken_sub\ninteger li_incoming_priority, li_instack_priority\nchar lc_temp_char\nstring ls_temp_string\nld_result = 0\n\/\/********************************************************************\n\/\/ first check the syntax of the infix arithmetic expression and put\n\/\/ each token into the ls_infix_token array\n\/\/********************************************************************\nls_infix_str = lefttrim (infix_expr) + &quot;@&quot;\nls_currchar = left (ls_infix_str, 1)\nls_token = &quot;&quot;\nDO WHILE 1 = 1\n CHOOSE CASE ls_currchar\n  CASE &quot;@&quot;\n    exit\n  CASE &quot;^&quot;, &quot;*&quot;, &quot;\/&quot;, &quot;+&quot;, &quot;-&quot;, &quot;(&quot;, &quot;)&quot;\n    li_itoken_sub = li_itoken_sub + 1\n    ls_infix_token [li_itoken_sub] = ls_currchar\n    ls_infix_str = lefttrim (mid (ls_infix_str, 2))\n    ls_currchar = left (ls_infix_str, 1)\n  CASE &#039;0&#039;, &#039;1&#039;, &#039;2&#039;, &#039;3&#039;, &#039;4&#039;, &#039;5&#039;, &#039;6&#039;, &#039;7&#039;, &#039;8&#039;, &#039;9&#039;, &#039;.&#039;\n    DO WHILE 1 = 1\n      ls_token = ls_token + ls_currchar\n      ls_infix_str = Mid(ls_infix_str, 2)\n      lc_temp_char = Left(ls_infix_str, 1)\n      ls_temp_string = Mid(ls_infix_str, 2, 1)\n      IF lc_temp_char = &quot; &quot; AND IsNumber(ls_temp_string) THEN\n        ls_token = &quot; &quot;\n        Exit\n      END IF\n      ls_infix_str = LeftTrim(ls_infix_str)\n      ls_currchar = left (ls_infix_str, 1)\n      CHOOSE CASE ls_currchar\n        CASE &quot;@&quot;, &quot;^&quot;, &quot;*&quot;, &quot;\/&quot;, &quot;+&quot;, &quot;-&quot;, &quot;(&quot;, &quot;)&quot;\n           exit\n        END CHOOSE\n    LOOP\n    IF isnumber (ls_token) THEN\n      li_itoken_sub = li_itoken_sub + 1\n      ls_infix_token [li_itoken_sub] = ls_token\n      ls_token = &quot;&quot;\n    ELSE\n      \/\/messagebox (&quot;uf_eval_arithmetic_expression &quot;, &quot;invalid number&quot;)\n      return (infix_expr)\n    END IF\n    IF ls_currchar = &quot;@&quot; THEN\n      exit\n    END IF\n  CASE ELSE\n    \/\/messagebox (&quot;uf_eval_arithmetic_expression &quot;, &quot;invalid expression&quot;)\n    return (infix_expr)\n END CHOOSE\nLOOP\n\/\/********************************************************************\n\/\/ second convert the infix expression into postfix notation\n\/\/********************************************************************\nls_infix_token [li_itoken_sub + 1] = &quot;@&quot;\nli_stack_top = 0\nli_itoken_sub = 0\nli_ptoken_sub = 0\nDO WHILE 1 = 1\n li_itoken_sub = li_itoken_sub + 1\n ls_token = ls_infix_token [li_itoken_sub]\n CHOOSE CASE ls_token\n   CASE &quot;@&quot;\n     DO WHILE li_stack_top &gt; 0\n       li_ptoken_sub = li_ptoken_sub + 1\n       ls_postfix_token [li_ptoken_sub] = ls_operator_stack [li_stack_top]\n       li_stack_top = li_stack_top - 1\n     LOOP\n     exit\n   CASE &quot;)&quot;\n     DO WHILE ls_operator_stack [li_stack_top] &lt;&gt; &quot;(&quot;\n        li_ptoken_sub = li_ptoken_sub + 1\n        ls_postfix_token [li_ptoken_sub] = ls_operator_stack [li_stack_top]\n        li_stack_top = li_stack_top - 1\n     LOOP\n     li_stack_top = li_stack_top - 1\n   CASE &quot;^&quot;, &quot;*&quot;, &quot;\/&quot;, &quot;+&quot;, &quot;-&quot;, &quot;(&quot;\n     DO WHILE 1 = 1\n       CHOOSE CASE ls_token\n         CASE &quot;+&quot;, &quot;-&quot;\n            li_incoming_priority = 1\n         CASE &quot;*&quot;, &quot;\/&quot;\n            li_incoming_priority = 2\n         CASE ELSE\n            li_incoming_priority = 4\n       END CHOOSE\n       IF li_stack_top = 0 THEN\n          li_instack_priority = 0\n       ELSE\n         CHOOSE CASE ls_operator_stack [li_stack_top]\n           CASE &quot;+&quot;, &quot;-&quot;\n             li_instack_priority = 1\n           CASE &quot;*&quot;, &quot;\/&quot;\n             li_instack_priority = 2\n           CASE &quot;^&quot;\n             li_instack_priority = 3\n           CASE ELSE\n             li_instack_priority = 0\n           END CHOOSE\n       END IF\n       IF li_incoming_priority &gt; li_instack_priority THEN\n         exit\n       END IF\n       li_ptoken_sub = li_ptoken_sub + 1\n       ls_postfix_token [li_ptoken_sub] = ls_operator_stack [li_stack_top]\n       li_stack_top = li_stack_top - 1\n     LOOP\n     li_stack_top = li_stack_top + 1\n     ls_operator_stack [li_stack_top] = ls_token\n CASE ELSE\u00a0 \/* ls_token is an operand *\/\n    li_ptoken_sub = li_ptoken_sub + 1\n    ls_postfix_token [li_ptoken_sub] = ls_token\n END CHOOSE\nLOOP\n\/\/********************************************************************\n\/\/ third evaluate the postfix arithmetic expression. each token is\n\/\/ stored as a string occurance in the ls_postfix_token array\n\/\/********************************************************************\nls_postfix_token [li_ptoken_sub + 1] = &quot;@&quot;\nld_result = 0\nli_stack_top = 0\nli_ptoken_sub = 0\nDO WHILE 1 = 1\n li_ptoken_sub = li_ptoken_sub + 1\n ls_token = ls_postfix_token [li_ptoken_sub]\n CHOOSE CASE ls_token\n   CASE &quot;@&quot;\n     IF li_stack_top = 0 THEN\n       return &quot;&quot;\n     END IF\n     ld_result = round (ld_operand_stack [li_stack_top], precision)\n     return (string(ld_result, &quot;0.####&quot;))\n   CASE &quot;^&quot;, &quot;*&quot;, &quot;\/&quot;, &quot;+&quot;, &quot;-&quot;\n      IF ls_token = &quot;\/&quot; and ld_operand_stack [li_stack_top] = 0 THEN\n        \/\/messagebox (&quot;fx_eval_arith_expr&quot;, &quot;divide by zero error&quot;)\n        return (infix_expr)\n      END IF\n      IF li_stack_top &lt; 2 THEN\n         \/\/messagebox (&quot;uf_eval_arithmetic_expression &quot;, &quot;invalid expression&quot;)\n         return (infix_expr)\n      END IF\n      ld_operand1 = ld_operand_stack [li_stack_top - 1]\n      ld_operand2 = ld_operand_stack [li_stack_top]\n      CHOOSE CASE ls_token\n        CASE &quot;+&quot;\n          ld_temp_result = ld_operand1 + ld_operand2\n        CASE &quot;-&quot;\n          ld_temp_result = ld_operand1 - ld_operand2\n        CASE &quot;*&quot;\n          ld_temp_result = ld_operand1 * ld_operand2\n        CASE &quot;\/&quot;\n          ld_temp_result = ld_operand1 \/ ld_operand2\n        CASE ELSE\n          ld_temp_result = ld_operand1 ^ ld_operand2\n      END CHOOSE\n      ld_operand_stack [li_stack_top - 1] = ld_temp_result\n      li_stack_top = li_stack_top - 1\n  CASE ELSE\u00a0 \/* have an operand so add to stack *\/\n    li_stack_top = li_stack_top + 1\n    ld_operand_stack [li_stack_top] = dec (ls_token)\n END CHOOSE\nLOOP<\/pre>\n\n\n<p>Updated March 2021<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Below is a function which allows the user to enter an arithmetic expression and then evaluate it and return the result.\u00a0 This will work for addition (+), subtraction(-), multiplication(*), division(\/), and exponentiation(^).\u00a0\u00a0 You can also enter parenthesis to change the order of precedence if needed.\u00a0 You would call this from where ever you like to&hellip;<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[3,10],"tags":[12,16],"_links":{"self":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/29"}],"collection":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/comments?post=29"}],"version-history":[{"count":11,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/29\/revisions"}],"predecessor-version":[{"id":1728,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/posts\/29\/revisions\/1728"}],"wp:attachment":[{"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/media?parent=29"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/categories?post=29"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/anvil-of-time.com\/wp-json\/wp\/v2\/tags?post=29"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}