<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0

    http://blog.csdn.net/hunkcai/article/details/6125963


    前言

    表達式的計算是一個一般性的問題。在報表領域,經常會出現支持計算公式的需求。MS Office Excel中的函數計算就是一個很好的參考例子。

    本文提供一個表達式引擎的設計方案,能夠滿足報表領域的復雜計算要求。

     

    一個良好的表達式引擎應該支持基本的二元運算和函數調用,而且二元運算能夠嵌套函數調用,函數調用也能夠嵌套二元運算,比如:

    例子1:=2>1&&((Num(1)+2*Num((Num(2)+2)*3/Num(2)))/2>0||2>1)&&0>1,執行結果:0

    例子2:=Switch(Num(1),是, Num(0),否),執行結果:是

    例子3:=Switch(20<10,1 ,20>=10, 20 + 20*0.1),執行結果:22

     

    當然,實際的應用里,表達式中要支持變量的綁定,比如:

    例子1(計算稅后金額):=Fields!數量.Value * Fields!單價.Value*(1 + Fields!稅率.Value / 100)

    例子2(不同價格不同稅后金額):=Fields!數量.Value*Fields!單價.Value*Switch(Fields!單 價.Value<100, 1.1, Fields!單價.Value<500, 1.08, Fields!單價.Value<800, 1.07)

     

    至于常用的一元運算,能夠通過函數調用就很方便的實現,例如:取非,Not(exp1)。

     

    表達式的定義

    要支持二元運算能夠嵌套函數調用,函數調用也能夠嵌套二元運算,需要采用解析器設計模式,定義數個表達式對象,用表達式對象樹來描述表達式字符串。

    值表達式:用來描述一個常量或變量,例如:1.1,Fields!數量.Value,Parameters!經手人.Value,字符串

    二元表達式:用來描述一個二元運算,例如:exp1 + exp2,exp1

    函數表達式:用來描述一個函數調用,例如:Num(exp1),Sum(exp1), Switch(cond1, proc1, cond2, proc2…)

     

    運算符優先級

    運算符優先級很重要,決定了運算的順序,特別是括號,能夠改變表達式的運算順序。

    優先級

    運算符

    說明

    -1

    (

    左括號

    -1

    )

    右括號

    -2

    ^

    冪運算

    -3

    *

    -3

    /

    -3

    %

    取余

    -4

    +

    -4

    -

    -5

    <

    小于

    -5

    <=

    小于等于

    -5

    >

    大于

    -5

    >=

    大于等于

    -6

    ==

    等于

    -6

    !=

    不等于

    -7

    &&

    邏輯與

    -8

    ||

    邏輯或

     

    表達式引擎的工作流程

     

    二元運算解析生成后綴表達式數組的過程

    中綴表達式解析成后綴表達式的方法如下,要借用一個臨時堆棧stack,輸出是后綴表達式數組output:

    (1)從右向左依次讀取表達式字符串str。

    (2)如果str是操作數(常量或變量),輸出到output。

    (3)如果str是運算符(含左右括號),則做以下判斷:

        a) 如果str = '(',放入堆棧stack。

        b)如果str = ')',依次彈出堆棧stack中的運算符輸出到output,直到遇到'('為止。

        c)如果str不是')'或者'(',那么就和堆棧stack頂點位置的運算符top做優先級比較。

          1)如果top是'('或者str優先級比top高,那么將str放入堆棧stack。

          2)如果str優先級低于或者等于top,那么輸出top到output,然后將str放入堆棧stack。

    (4)如果表達式字符串已經讀取完成,而堆棧stack中還有運算符時,依次由頂端輸出到output。

     

    后綴表達式數組生成表達式對象樹的過程

    計算后綴表達式的方法如下,要借用一個臨時堆棧stack:

    (1)從左向右掃描后綴表達式數組,依次取出一個數組元素data。

    (2)如果data是表達式,就壓入堆棧stack。

    (3)如果data是運算符,就從堆棧stack中彈出此運算符需要用到的表達式的個數(二元運算符需要2個),創建一個新二元表達式,然后把二元表達式壓入堆棧stack。

    (4)如果數組處理完畢,堆棧stack中最后剩余的表達式就是最終結果。

     

    例如,表達式=(Num(1)+2*Num(Num(2)+2*3/Num(2)))/2,生成的后綴表達式數組如下:

    0:    Method{num, [Const(1)]}

    1:    Const(2)

    2:    Method{num, [Binary{+, Method{num, [Const(2)]}, Binary{/, Binary{*, Const(2), Const(3)}, Method{num, [Const(2)]}}}]}

    3:    *

    4:    +

    5:    Const(2)

    6:    /

    該后綴表達式數組生成的表達式對象樹如下:

    Binary{/, Binary{+, Method{num, [Const(1)]}, Binary{*, Const(2), Method{num, [Binary{+, Method{num, [Const(2)]}, Binary{/, Binary{*, Const(2), Const(3)}, Method{num, [Const(2)]}}}]}}}, Const(2)}

     

    剩下的工作就是執行表達式對象樹,輸出結果。

    posted on 2012-11-05 17:32 SIMONE 閱讀(683) 評論(0)  編輯  收藏 所屬分類: JAVA
    主站蜘蛛池模板: 亚洲成色在线影院| 亚洲AV无码成人精品区蜜桃| 亚洲精品国产精品国自产观看| 国产成人综合亚洲| 五级黄18以上免费看| 国产精品免费观看调教网| 桃子视频在线观看高清免费完整| 女人张腿给男人桶视频免费版| 亚洲电影日韩精品| 国产成人精品123区免费视频| 亚洲综合色区在线观看| 久久亚洲精品成人AV| 亚洲av无码国产精品色午夜字幕 | 亚洲无线一二三四区手机| 国产AV无码专区亚洲AV男同| 亚洲一级高清在线中文字幕| 亚洲av无码有乱码在线观看| 91精品全国免费观看青青| 国产日本一线在线观看免费| 免费h黄肉动漫在线观看| 久久亚洲免费视频| 亚洲欧美综合精品成人导航| 两性色午夜视频免费网| 国产乱码免费卡1卡二卡3卡| 亚洲国产一区明星换脸| 亚洲福利视频网址| 搜日本一区二区三区免费高清视频| 免费国产黄网站在线观看视频| 手机看片久久国产免费| 亚洲av无码一区二区三区不卡| 亚洲欧洲AV无码专区| 久久香蕉国产线看免费| 日本一道本高清免费| 亚洲免费视频网站| 美女黄色免费网站| 波多野结衣在线免费观看| 2048亚洲精品国产| 国产成人亚洲综合一区| 久久免费视频观看| 免费国产小视频在线观看| 亚洲国产精品午夜电影|