iT邦幫忙

1

C# 環保署判斷問題 (範圍區間邏輯 , 和計算公式)

  • 分享至 

  • xImage

https://ithelp.ithome.com.tw/upload/images/20180719/20109425sfpT9PC2OC.jpg

https://ithelp.ithome.com.tw/upload/images/20180719/20109425aOA6NLLdGO.jpg

https://ithelp.ithome.com.tw/upload/images/20180719/20109425Tm0yLVYZHf.jpg

請問圖一 和 圖二 和 圖三 如果 分別各要寫成一個fuction 的話要怎麼寫?

有大大可以給小弟我一個方向嗎?

或是有一個範例/images/emoticon/emoticon02.gif

  protected static Color ChangeColor(string AQI)
        {
            int number = 0;
            if (int.TryParse(AQI, out number))
            {
                if (number > 301) return Color.DarkRed;
                else if (number > 201) return Color.Purple;
                else if (number > 151) return Color.Red;
                else if (number > 101) return Color.Orange;
                else if (number > 51) return Color.Yellow;
                else return Color.Green;
            }
            return Color.Green;
        }
  protected static string setText(string Text)
        {
            int number = 0;

            if (int.TryParse(Text, out number))
            {
                if (number >= 50) return "良好".ToString();
                else if (number >= 100) return "普通".ToString();
                else if (number >= 150) return "對敏感族群\n不健康 ".ToString();
                else if (number >= 200) return "對所有族群\n不健康".ToString();
                else if (number >= 300) return "非常不健康".ToString();
                else if (number >= 400) return "危害".ToString();

            }
            return "良好".ToString();
 protected static string setPic(string AQI)
        {
            int number = 0;
            if (int.TryParse(AQI, out number))
            {
                if (number < 50) return @"D:\****g\picture\1.png"; //幸福臉
                else if (number <= 100) return @"D:\****g\picture\2.png"; // 笑臉
                else if (number <= 150) return @"D:\***\picture\3.png"; // 無奈臉
                else if (number <= 200) return @"D:\*******picture\6.png"; //  流汗臉
                else if (number <= 300) return @"D:\*****\picture\7.png"; // 哭哭臉
                else if (number <= 400) return @"D:\****cture\8.png";  // 口罩臉
                else if (number >= 400) return @"D:\***icture\8.png"; // 口罩臉
            }
            return @"D:\***\icture\1.png";
        }
看更多先前的討論...收起先前的討論...
froce iT邦大師 1 級 ‧ 2018-07-19 16:18:26 檢舉
你會用筆算的話,我想要寫這個程式沒啥難度吧。
Homura iT邦高手 1 級 ‧ 2018-07-19 16:20:03 檢舉
用力想
用力寫啊...
ted8224 iT邦新手 5 級 ‧ 2018-07-19 17:07:01 檢舉
會用手寫 , 但..不太會寫..rrr , Help!! ,我有寫 , 判斷 底圖, 顏色 ...
小魚 iT邦大師 1 級 ‧ 2018-07-19 20:22:48 檢舉
先把目前的進度PO出來吧
ted8224 iT邦新手 5 級 ‧ 2018-07-20 08:02:01 檢舉
@小魚大...
先把你的每個欄位計算都寫出來,然後放上來吧,覺得寫成function容易,反而計算比較麻煩,另外盡量不用多個 else if 這種語法,寫成list處理比較好~
應該先講清楚你這個程式的目的或要做什麼工作。
這三張圖不會變成三個function,準確的說要變幾個function是看你的目的
你貼的三段code看起來就是有人已經把AQI算出來,把AQI丟給你
然後你的程式根據AQI去改變某個或某些UI的顯示

而且我看起來根本也不用算,直接拿收到的數據去查表就好了
如果不是問題真的就這麼單純,不然就是你給的資訊不夠
ted8224 iT邦新手 5 級 ‧ 2018-07-21 14:09:26 檢舉
@ra 大.. 其實有點複雜.. 要寫很多判斷邏輯.. 雖然我也想從資料庫撈計算好的資料,卻被說 要撈別人的..冏...
ted8224 iT邦新手 5 級 ‧ 2018-07-21 14:12:22 檢舉
@kk大... 目前 我也還在想.. 我是問 有人告訴我 笑臉 顏色 AQI 數值 綁再一起..設定 case 1 或是 int 1 之類... 再用多少數去 去if else 去return 1... 可是重點是 要怎麼把 3種? 一個 數字 一個顏色 一個字串 綁成一個物件? 讓我去return呢?綁成一個class?綁成一個fuction?綁成一個物件?.. 今晚看書研究 搞懂他.... 謝謝各位大大回復留言
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
小碼農米爾
iT邦高手 1 級 ‧ 2018-07-23 02:12:57
最佳解答

題目蠻有趣的,第一張圖的對照表小弟做出來了,
不過圖片下方第三點說明不是很了解,
內容提到 AQI 200 以上,這會橫跨 2 個區間,
且查了一下政府觀測站的網站,並沒有提供 SO2 24hr 的資料,這樣該如何計算呢,
這部分覺得有點困惑。

先附上對照表的程式碼:

AQI_Table_Ex

public static class AQI_Table_Ex
{
    /// <summary>
    /// 產生空氣品質指標對照表資料
    /// </summary>
    /// <returns></returns>
    public static List<AQI_Table> Create()
    {
        var table = new List<AQI_Table>
        {
            new AQI_Table
            {
                LevelType = LevelType.L1,   
                AQI_low = 0,
                AQI_hight = 50,
                O3_8hr_low = 0.000m,
                O3_8hr_hight = 0.054m,
                O3_1hr_low = null,
                O3_1hr_hight = null,
                PM2_5_low = 0.0m,
                PM2_5_hight = 15.4m,
                PM10_low = 0m,
                PM10_hight = 54m,
                CO_8hr_low = 0m,
                CO_8hr_hight = 4.4m,
                SO2_1hr_low = 0m,
                SO2_1hr_hight = 35m,
                SO2_8hr_low = null,
                SO2_8hr_hight = null,
                NO2_1hr_low = 0m,
                NO2_1hr_hight = 53m,
                Text =  "良好",
                Color = Color.Green,
                PicPath = "picture1.png",
            },
            new AQI_Table
            {
                LevelType = LevelType.L2,
                AQI_low = 51,
                AQI_hight = 100,
                O3_8hr_low = 0.055m,
                O3_8hr_hight = 0.070m,
                O3_1hr_low = null,
                O3_1hr_hight = null,
                PM2_5_low = 15.5m,
                PM2_5_hight = 35.4m,
                PM10_low = 55m,
                PM10_hight = 125m,
                CO_8hr_low = 4.5m,
                CO_8hr_hight = 9.4m,
                SO2_1hr_low = 36m,
                SO2_1hr_hight = 75m,
                SO2_8hr_low = null,
                SO2_8hr_hight = null,
                NO2_1hr_low = 54m,
                NO2_1hr_hight = 100m,
                Text =  "普通",
                Color = Color.Yellow,
                PicPath = "picture2.png",
            },
            new AQI_Table
            {
                LevelType = LevelType.L3,
                AQI_low = 101,
                AQI_hight = 150,
                O3_8hr_low = 0.071m,
                O3_8hr_hight = 0.085m,
                O3_1hr_low = 0.125m,
                O3_1hr_hight = 0.164m,
                PM2_5_low = 35.5m,
                PM2_5_hight = 54.4m,
                PM10_low = 126m,
                PM10_hight = 254m,
                CO_8hr_low = 9.5m,
                CO_8hr_hight = 12.4m,
                SO2_1hr_low = 76m,
                SO2_1hr_hight = 185m,
                SO2_8hr_low = null,
                SO2_8hr_hight = null,
                NO2_1hr_low = 101m,
                NO2_1hr_hight = 360m,
                Text =  "對敏感族群\n不健康",
                Color = Color.Orange,
                PicPath = "picture3.png",
            },
            new AQI_Table
            {
                LevelType = LevelType.L4,
                AQI_low = 151,
                AQI_hight = 200,
                O3_8hr_low = 0.086m,
                O3_8hr_hight = 0.105m,
                O3_1hr_low = 0.165m,
                O3_1hr_hight = 0.204m,
                PM2_5_low = 54.5m,
                PM2_5_hight = 150.4m,
                PM10_low = 255m,
                PM10_hight = 354m,
                CO_8hr_low = 12.5m,
                CO_8hr_hight = 15.4m,
                SO2_1hr_low = 186m,
                SO2_1hr_hight = 304m,
                SO2_8hr_low = 186m,
                SO2_8hr_hight = 304m,
                NO2_1hr_low = 361m,
                NO2_1hr_hight = 649m,
                Text =  "對所有族群\n不健康",
                Color = Color.Red,
                PicPath = "picture4.png",
            },
            new AQI_Table
            {
                LevelType = LevelType.L5,
                AQI_low = 201,
                AQI_hight = 300,
                O3_8hr_low = 0.106m,
                O3_8hr_hight = 0.200m,
                O3_1hr_low = 0.205m,
                O3_1hr_hight = 0.404m,
                PM2_5_low = 150.5m,
                PM2_5_hight = 250.4m,
                PM10_low = 355m,
                PM10_hight = 424m,
                CO_8hr_low = 15.5m,
                CO_8hr_hight = 30.4m,
                SO2_1hr_low = null,
                SO2_1hr_hight = null,
                SO2_8hr_low = 305m,
                SO2_8hr_hight = 604m,
                NO2_1hr_low = 650m,
                NO2_1hr_hight = 1249m,
                Text =  "非常不健康",
                Color = Color.Purple,
                PicPath = "picture5.png",
            },
            new AQI_Table
            {
                LevelType = LevelType.L6,
                AQI_low = 300,
                AQI_hight = 400,
                O3_8hr_low = null,
                O3_8hr_hight = null,
                O3_1hr_low = 0.405m,
                O3_1hr_hight = 0.504m,
                PM2_5_low = 250.5m,
                PM2_5_hight = 350.4m,
                PM10_low = 425m,
                PM10_hight = 504m,
                CO_8hr_low = 30.5m,
                CO_8hr_hight = 40.4m,
                SO2_1hr_low = null,
                SO2_1hr_hight = null,
                SO2_8hr_low = 605m,
                SO2_8hr_hight = 804m,
                NO2_1hr_low = 1250m,
                NO2_1hr_hight = 1649m,
                Text =  "危害",
                Color = Color.DarkRed,
                PicPath = "picture6.png",
            },
            new AQI_Table
            {
                LevelType = LevelType.L7,
                AQI_low = 400,
                AQI_hight = 500,
                O3_8hr_low = null,
                O3_8hr_hight = null,
                O3_1hr_low = 0.505m,
                O3_1hr_hight = 0.604m,
                PM2_5_low = 350.5m,
                PM2_5_hight = 500.4m,
                PM10_low = 505m,
                PM10_hight = 604m,
                CO_8hr_low = 40.5m,
                CO_8hr_hight = 50.4m,
                SO2_1hr_low = null,
                SO2_1hr_hight = null,
                SO2_8hr_low = 805m,
                SO2_8hr_hight = 1004m,
                NO2_1hr_low = 1650m,
                NO2_1hr_hight = 2049m,
                Text =  "危害",
                Color = Color.DarkRed,
                PicPath = "picture7.png",
            },
        };
        return table;
    }
}

AQI_Table

/// <summary>
/// 空氣品質指標對照表
/// </summary>
public class AQI_Table
{
    public decimal? O3_1hr_low { get; set; }
    public decimal? O3_1hr_hight { get; set; }
    public decimal? O3_8hr_low { get; set; }
    public decimal? O3_8hr_hight { get; set; }
    public decimal? SO2_1hr_low { get; set; }
    public decimal? SO2_1hr_hight { get; set; }
    public decimal? SO2_8hr_low { get; set; }
    public decimal? SO2_8hr_hight { get; set; }
    public decimal? CO_8hr_low { get; set; }
    public decimal? CO_8hr_hight { get; set; }
    public decimal? NO2_1hr_low { get; set; }
    public decimal? NO2_1hr_hight { get; set; }
    public decimal? PM2_5_low { get; set; }
    public decimal? PM2_5_hight { get; set; }
    public decimal? PM10_low { get; set; }
    public decimal? PM10_hight { get; set; }
    public int AQI_low { get; set; }
    public int AQI_hight { get; set; }
    public LevelType LevelType { get; set; }
    public string Text { get; set; }
    public Color Color { get; set; }
    public string PicPath { get; set; }
}

LevelType

/// <summary>
/// AQI 等級
/// </summary>
public enum LevelType
{
    L1 = 1,
    L2,
    L3,
    L4,
    L5,
    L6,
    L7,
}

PollutantType

/// <summary>
/// 汙染物類型
/// </summary>
public enum PollutantType
{
    O3_8hr,
    O3_1hr,
    PM2_5,
    PM10,
    CO_8hr,
    SO2_1hr,
    SO2_8hr,
    NO2_1hr
}

函數我就沒有特別寫,可以用 Linq 查表。

var table = AQI_Table_Ex.Create();
var item = table
    .Where(it => it.AQI_low <= AQI && it.AQI_hight >= AQI)
    .FirstOrDefault();

好晚了今天先到這裡,明天有空再繼續研究 XD。

看更多先前的回應...收起先前的回應...
ted8224 iT邦新手 5 級 ‧ 2018-07-23 10:14:47 檢舉

關於計算公式,當然我寫的是有問題,我只是把構想先寫看看

 private static void PM25_C(Double C25)        //PM2.5   ( C )  移動平均

    {
        string sq16 = @"Select TOP12 **** FROM *** WHERE **** ORDER BY M_DateTime DESC";
        string sq17 = @"Select TOP4 ***  FROM ***WHERE *** ORDER BY M_DateTime DESC";

     
        DataTable dt16= SqlCommand(sq16);
        DataTable dt17 = SqlCommand(sq17);

        Double PM12H_Ave = dt16 / 12;

        Double PM4H_Ave = dt17 / 4;

        Double PM25_C = 0.5 * PM12H_Ave + 0.5 * PM4H_Ave;

        dt16.Dispose();
        dt17.Dispose();

    }

    private static void PM10_C(Double C24)        //PM10   ( C )  移動平均

    {
        string sq18 = @"Select TOP12 *** FROM *** ORDER BY M DESC";
        string sq19 = @"Select TOP4  *** FROM *** WHERE *** ORDER BY M_DateTime DESC";

        DataTable dt18 = SqlCommand(sq18);
        DataTable dt19 = SqlCommand(sq19);

        Double PM12H_Ave = dt18 / 12;

        Double PM4H_Ave = dt19 / 4;

        Double PM25_C = 0.5 * PM12H_Ave + 0.5 * PM4H_Ave;

        dt18.Dispose();
        dt19.Dispose();
    }

    //8小時移動平均值計算方式:取最近連續8小時移動平均值 (4筆有效)

    private static void O38H_C(Double O3_8)        // O3 8H   移動平均 

    {
        string sq20 = @"Select TOP8 *** FROM ** WHERE ***RDER BY M_DateTime DESC";


        DataTable dt20 = SqlCommand(sq20);

        Double O38H_Ave = dt20 / 8;

        dt20.Dispose();

    }

    private static void CO8H_C(Double CO_8)        // CO 8H   移動平均 

    {
        string sq21 = @"Select TOP8 *** FROM *** ORDER BY M_DateTime DESC";


        DataTable dt21 = SqlCommand(sq21);

        Double O38H_Ave = dt21 / 8;

        dt21.Dispose();

    }

    //SO2  24H 移動平均值

    private static void SO2_24H_C(Double SO2_24)        // SO2  24H  濃度平均值

    {
        string sq22 = @"Select TOP24  *** FROM *** WHERE**R BY M_DateTime DESC";


        DataTable dt22 = SqlCommand(sq22);

        Double O38H_Ave = dt22 / 24;

        dt22.Dispose();

    }

ted8224 iT邦新手 5 級 ‧ 2018-07-23 10:19:55 檢舉

裡面的前面幾小時之類移動平均之類,我是取資料庫比如Top 4,然後變
dt
在把dt / 多少 ;
當然那樣是錯的

**前4小時2筆有效,前12小時6筆有效

**4筆有效

使用布林代數 true ?

ted8224 iT邦新手 5 級 ‧ 2018-07-23 10:34:00 檢舉
  private static void All_AQI(Double I)  // AQI 計算公式


    {
        int Ihigh = 0;   // AQI 範圍數值 大 表格資料
        int Ilow = 0;    // AQI 範圍數值 小 表格資料
        Double Chigh = 0;  // PM2.5 表格 大
        Double Clow = 0;   // PM2.5 表格 小
        Double C = 0;     // 移動平均?  汙燃物 輸入值  活的
        Double IAQI = ((Ihigh - Ilow) / (Chigh - Clow)) * (C - Clow) + Ilow;

    }

移動平均計算方式,我和您想的差不多,查出 TOP 再去算平均。

前4小時2筆有效,前12小時6筆有效

這段話,我猜測每1小時會紀錄1筆觀測資料,

前4小時會有4筆資料,TOP 4 再 WHERE 現在時間-觀測時間<=4小時

如果資料大於等於2筆則為有效值,如果資料小於2筆 (例如監測系統故障),則移動平均因資料不足為無效值。

以上是我的猜測,不確定,哈哈哈。

最後您的 All_AQI 是計算單項 IAQI 的函數,可以利用此函數,算出各項的 IAQI 後取最大值,就是我們期望的 AQI 結果。

ted8224 iT邦新手 5 級 ‧ 2018-07-24 08:17:34 檢舉

是的 每一小時撈一次資料庫,是阿..計算後 6項取最大值 為本整點的AQI,只是我還在想怎麼樣移動平均怎麼寫,我只寫大概,比如下面這個是錯的

Double PM12H_Ave = dt16 / 12;

Double PM4H_Ave = dt17 / 4;

謝謝大大 一值分享你的方法與交流

C# 可以這樣做,不過如果能用 SQL 更簡單。

var PM12H_Ave = dt16.AsEnumerable()
    .Select(it => double.Parse(it["PM12H"].ToString()))
    .Sum() / 12;

前4小時2筆有效,有效的意義我理解正確嗎? /images/emoticon/emoticon19.gif

哈哈哈,覺得算 AQI 蠻有趣的。

ted8224 iT邦新手 5 級 ‧ 2018-07-24 10:49:57 檢舉

前4小時2筆有效,前12小時6筆有效

應該是我取資料庫

我有一個狀態是 比如 010 , 011 之類有效,020 ,021 之類無效,其實我有一個Excel 表格
以下是我秀畫面判斷的資料

  protected static string KBstatus(string status)
        {            
            int number = 0;
            if (int.TryParse(status, out number))
            {
                if (number == 020) return "校正中";
                else if (number == 021) return "校正中";
                else if (number == 026) return "校正中";
                else if (number == 030) return "校正中";
                else if (number == 031) return "維修中";
                else if (number == 038) return "定期保養";
                else if (number == 035) return "數據量不足";
            }
            return "校正中";
        }

其中 (020,021,026,030,031,038,035) 為資料庫撈資料 狀態值,所顯示代碼..

一開始我也以為有欄位註記,不過撈資料的邏輯想不通,
假設4小時內的資料有4筆,其中3筆有效,1筆無效,
那麼我只撈3筆有效中的前2筆嗎,覺得怪怪的,哈哈哈

ted8224 iT邦新手 5 級 ‧ 2018-07-24 14:29:07 檢舉

恩恩 對 4小時 2筆有效, 只要 其中 裡面 2筆狀態是顯示為正確狀態,就可以了

撈3筆有效中前兩筆因該是這樣

ted8224 iT邦新手 5 級 ‧ 2018-07-25 10:48:45 檢舉

@fy 大 請問您說的這段 函式

var table = AQI_Table_Ex.Create();
var item = table
    .Where(it => it.AQI_low <= AQI && it.AQI_hight >= AQI)
    .FirstOrDefault();

還要多哪一些西呢?我改成

 void Main()
  { var table = AQI_Table_Ex.Create();

            var item = table
                .Where(it => it.AQI_low <= AQI && it.AQI_hight >= AQI)
                .FirstOrDefault();
                }

其中AQI 沒有設定他的變數 讀不他這一個變數

恩要在最上面宣告。 /images/emoticon/emoticon25.gif

var AQI = 100;
ted8224 iT邦新手 5 級 ‧ 2018-07-26 09:58:07 檢舉

請問我的 移動平均 和AQI ,關於裡面的 return , 丟到 excel 空格裡

  public   double  get_O3_8H_average()   //O3_8H   ( C )  移動平均
     {
            string sq14 = @"Select TOP8 A525V FROM P1234567_Hr_2018 WHERE DP_NO = 'A009' ORDER BY M_DateTime DESC";
             

            DataTable dt14 = SqlCommand(sq14);

            //前8小時平均
            var O3_8H_C = dt14.AsEnumerable()
                           .Select(it => double.Parse(it["O3_8H"].ToString()))
                           .Sum() / 12;
                       
            dt14.Dispose();

            return O3_8H_C;
                 

        }

上面 我return 出來的 O3_8H_C,和I 其他地方不能使用他嗎?

我有一個地方是插入移動平均

可是卻找不到 : O3_8H_C ,請問大大 不是我上面公式 有return 出來了?

然後把移動平均和AQI和在一起是這樣嗎?

https://ithelp.ithome.com.tw/upload/images/20180726/201094259dlrQ5EFOO.jpg

https://ithelp.ithome.com.tw/upload/images/20180726/2010942508YRIZctZV.jpg

求解紅色蝌蚪/images/emoticon/emoticon13.gif

ted8224 iT邦新手 5 級 ‧ 2018-07-26 10:13:28 檢舉
  public static double AQI(Double I) // AQI 計算公式
  {
            int Ihigh = 0;   // AQI 範圍數值 大 表格資料
            int Ilow = 0;    // AQI 範圍數值 小 表格資料
            Double Chigh = 0;  // PM2.5 表格 大
            Double Clow = 0;   // PM2.5 表格 小
            Double C = 0;     // 移動平均?  算出來數值輸入值  活的
            


             I = ((Ihigh - Ilow) / (Chigh - Clow)) * (C - Clow) + Ilow;

            return I;

        }
  //算好移動平均  插入AQI 計算公式
        public static void  Main ()
        {
          
            double average = get_PM25_average();
            double AQIcal = AQI(average);
          
        }

哈哈哈,這樣看不太出來,我試著回答看看。

O3_8H_C ,請問大大 不是我上面公式 有return 出來了

有 return,是不是外面沒有宣告變數去接函數的回傳?

函數在同一個類別內可以直接呼叫,get_PM25_average 是不是沒有宣告或不在同類別?

ted8224 iT邦新手 5 級 ‧ 2018-07-26 13:13:39 檢舉

不好意思 請問 要如何去接函數的回傳?..

這樣~

var O3_8H_C = get_O3_8H_average();
sheet.Range["F3"].Text = O3_8H_C.ToString();
ted8224 iT邦新手 5 級 ‧ 2018-07-26 15:27:08 檢舉

/images/emoticon/emoticon02.gif

出來數值都是:19.96916667 和 21.35666666

把公式的 var 和 double 都改成int

int O3_8H_C = get_O3_8H_average();
sheet.Range["F3"].Text = O3_8H_C.ToString();

就跑個啥 字串功能不對 冏.

難道問題點 在取決於 資料庫來源 本來就屬於 小數?(double ,var) 型別

冏. 讀來源資料庫 真的都小數, 難怪 改int 說字串啥問題

可惜出來解果, 依照環保局來說 都是整數說..
謝謝大大 回復

哈哈哈,小數點正常,因為我們函數的回傳型態是 double,
var 是 推斷型別,它不是真正的型態,編譯後 var 會以函數的回傳 double 取代。

C# 是強型別的語言,因此不能用 int 去接收 double 的值。

int O3_8H_C = get_O3_8H_average();

如果想要取整數,可以用 Round 函數先四捨五入到整數位,再轉型成 int。

var O3_8H_C = (int)Math.Round(get_O3_8H_average());
ted8224 iT邦新手 5 級 ‧ 2018-07-26 16:33:17 檢舉

我發現 移動平均 好了之後, 再丟進 大大給的 table AQI 表
弄成 AQI 公式 好難啊...
6個狀態 丟進去
算成6個AQI (A,B,C,D,E,F)

比如A的AQI大 取他,AQI 為整點AQI值

問題是怎麼把移動平均等各項數值
丟到大您的表?

丟好之後判斷在哪一個區間,在丟到AQI 計算公式

計算公式我寫好,只是不曉得,怎麼去 餵入數值../images/emoticon/emoticon02.gif

/images/emoticon/emoticon06.gif

用 SQL + DataTable 應該會比較好處理,用 Class 要寫好長,哈哈哈
研究了一下表達式樹,雖然精簡了程式碼,不過比較難懂,給您參考看看。

/// <summary>
/// 計算 AQI
/// </summary>
public static int CalcAQI(this List<AQI_Table> airQualityTable, 
    decimal O3_8hr, 
    decimal O3_1hr, 
    decimal PM2_5, 
    decimal PM10, 
    decimal CO_8hr, 
    decimal SO2_1hr, 
    decimal NO2_1hr)
{
    //汙染物陣列
    var pollutantList = new List<Tuple<PollutantType, decimal>>
    {
        new Tuple<PollutantType, decimal>(
            PollutantType.O3_8hr, O3_8hr),
        new Tuple<PollutantType, decimal>(
            PollutantType.O3_1hr, O3_1hr),
        new Tuple<PollutantType, decimal>(
            PollutantType.PM2_5, PM2_5),
        new Tuple<PollutantType, decimal>(
            PollutantType.PM10, PM10),
        new Tuple<PollutantType, decimal>(
            PollutantType.CO_8hr, CO_8hr),
        new Tuple<PollutantType, decimal>(
            PollutantType.SO2_1hr, SO2_1hr),
        new Tuple<PollutantType, decimal>(
            PollutantType.NO2_1hr, NO2_1hr),
    };
    
    var pollutantRowList = pollutantList.Select(it =>
    {
        //產生可動態取得 low、high 的表達式樹
        var pollutantName = it.Item1.ToString();
        var type = typeof(AQI_Table);
        var itParam = Expression.Parameter(type, "it");
        var lowGetter = Expression.Property(itParam, 
            type.GetProperty($"{pollutantName}_low"));
        var highGetter = Expression.Property(itParam, 
            type.GetProperty($"{pollutantName}_hight"));
        var getLow = Expression.Lambda<Func<AQI_Table, decimal?>>(
            lowGetter, itParam).Compile();
        var getHigh = Expression.Lambda<Func<AQI_Table, decimal?>>(
            highGetter, itParam).Compile();

        var pollutantType = it.Item1;
        var C = it.Item2;

        //查表
        var row = airQualityTable
            .Where(itt => C >= getLow(itt) && C <= getHigh(itt))
            .FirstOrDefault();
        
        //查不到回傳 null
        return row == null ? null : new
        {
            pollutantType = pollutantType,
            row = row,
            C = C,
            Clow = getLow(row).Value,
            Chigh = getHigh(row).Value,
            Ilow = row.AQI_low,
            Ihigh = row.AQI_hight,
        };
    });

    //IAQI 計算公式
    var calc = (Func<decimal, decimal, decimal, int, int, int>)
        ((C, Clow, Chigh, Ilow, Ihigh) =>
    {
        return (int)Math.Ceiling(
            (Ihigh - Ilow) / (Chigh - Clow) * (C - Clow) + Ilow);
    });

    //計算 IAQI
    var IAQI = pollutantRowList.Where(it => it != null)
        .Select(it => new
        {
            pollutantType = it.pollutantType,
            IAQI = calc(it.C, it.Clow, it.Chigh, it.Ilow, it.Ihigh),
        });

    //算出最大值
    return IAQI.Max(it => it.IAQI);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
    var table = AQI_Table_Ex.Create();
    var AQI = table.CalcAQI(38m * 1000, 21m * 1000, 18m, 34m, 
        0.30m, 1.8m, 5.5m);
}
ted8224 iT邦新手 5 級 ‧ 2018-07-27 09:43:21 檢舉

不好意思,有點看不太懂, 最後一段,大概要新增一個 Button ,其中有一段是

table.CalcAQI(38m * 1000, 21m * 1000, 18m, 34m, 0.30m, 1.8m, 5.5m, out AQI, out pollutantTypes);

請問裡面數字是?我對過表格,數字好像沒在裡面
您的意思是本來是要寫一個class,功能會有把計算好各項移動公式丟到您之前創造的Table , 去判斷他落在哪一個區間, 判斷好後丟到AQI計算公式, 然後重複6次, 然後有6個,然後在取最大,即為該整點取樣AQI數值

因為我把您code 貼有 一些 紅色蝌蚪/images/emoticon/emoticon02.gif

https://ithelp.ithome.com.tw/upload/images/20180727/20109425p6NLdxnPJH.jpg

https://ithelp.ithome.com.tw/upload/images/20180727/20109425qbUL0vcqKe.jpg

然後表達式樹,.../images/emoticon/emoticon06.gif

數字是算好的移動平均,函數的參數就是那七項,後面兩個 out 則會回傳我們算出來七項中的最大值,也就是 AQI,和指標汙染物。

public static int CalcAQI(this List<AQI_Table> airQualityTable, 
    decimal O3_8hr, 
    decimal O3_1hr, 
    decimal PM2_5, 
    decimal PM10, 
    decimal CO_8hr, 
    decimal SO2_1hr, 
    decimal NO2_1hr)

紅色蝌蚪的部分:
Button_Click 函數是我自己測試用的 (WPF專案),您取中間的程式就好。
CalcAQI 函數要宣告在 AQI_Table_Ex 類別內。

後來想想 out pollutantTypes 其實可以拉到外面做,CalcAQI 就單純的計算 AQI 就好,這樣比較單純,我修改一下。

ted8224 iT邦新手 5 級 ‧ 2018-07-27 16:30:24 檢舉

大大我大概知道您 表達式樹 ,當最上面, 把上面之前 算好 移動平均丟到 下層 然後一層一層下去 一直到這裡

   //回傳結果
                AQI = max;
                //指標汙染物可以有多個
                pollutantTypes = IAQI
                    .Where(it => it.IAQI == max)
                    .Select(it => it.pollutantType)
                    .ToArray();
            }

這狀況如果沒錯的話,指標汙染物為6種AQI 的最大值,取其該項的AQI,為目前AQI

然後
https://ithelp.ithome.com.tw/upload/images/20180727/20109425ppmwaX4EJL.jpg

靜態型別關係,大概是指

 public static void CalcAQI(this List<AQI_Table> airQualityTable,

上面 我改成

static void 

刪掉,只單純 定義 public 之類,雖然上面From 靜態關係 紅色蝌蚪會消失
但是接下來This等等 之類 又有新的紅色蝌蚪
/images/emoticon/emoticon06.gif

然後

  public static void CalcAQI(this List<AQI_Table> airQualityTable,
                decimal O3_8H_C,
                decimal O3_1hr,
                decimal PM25_C,
                decimal PM10_C,
                decimal CO_8H_C,
                decimal SO2_24H_C,
                decimal NO2_1hr,
                out int AQI,

您這段意思是取移動平均上面return 出來後的數值,我其中變數 是改成我上面取的變數這樣.

至於後面那部分
取後面中間程式我就不曉的了..
/images/emoticon/emoticon08.gif
感謝大大都一直為我解惑...

沒錯,程式邏輯如您所說。 /images/emoticon/emoticon34.gif

CalcAQI 函數要放在 AQI_Table_Ex 類別內,不是把 static 拿掉 XD,
CalcAQI 有修改成比較符合你的需求,下面的數值放算出來的各項移動平均。

var table = AQI_Table_Ex.Create();
var AQI = table.CalcAQI(38m * 1000, 21m * 1000, 18m, 34m, 
    0.30m, 1.8m, 5.5m);
ted8224 iT邦新手 5 級 ‧ 2018-07-30 11:01:21 檢舉

大大不好意思
六日試了很久..還是有點沒辦法
請問之前您貼的那一段函式
用 Linq 查表。 這一段還需要嗎?

var table = AQI_Table_Ex.Create();
var item = table
    .Where(it => it.AQI_low <= AQI && it.AQI_hight >= AQI)
    .FirstOrDefault();

然後CalcAQI 函數要放在 AQI_Table_Ex 類別內,意思是把它塞進class裡,我是連下面都塞進去了,然後再把

var table = AQI_Table_Ex.Create();
var AQI = table.CalcAQI(38m * 1000, 21m * 1000, 18m, 34m, 
    0.30m, 1.8m, 5.5m);

這一段也塞進去了
天啊~好多蝌蚪阿/images/emoticon/emoticon06.gif

 public static class AQI_Table_Ex
        {
            /// <summary>
            /// 產生空氣品質指標對照表資料
            /// </summary>
            /// <returns></returns>
            public static List<AQI_Table> Create()
            {
                var table = new List<AQI_Table>();

                {
                    //         |    Level   |    AQI  |     O3 8hr    |     O3 1hr    |     PM2.5     |    PM10   |      CO     |   SO2 1hr   |   SO2 8hr   |     NO2     |
                    new AQI_Table(LevelType.L1, 0, 50, 0.000m, 0.054m, null, null, 0.0m, 15.4m, 0m, 54m, 0m, 4.4m, 0m, 35m, null, null, 0m, 53m, "良好", Color.Green, @"D:\DocToImg\picture\1.png");
                    new AQI_Table(LevelType.L2, 51, 100, 0.055m, 0.070m, null, null, 15.5m, 35.4m, 55m, 125m, 4.5m, 9.4m, 36m, 75m, null, null, 54m, 100m, "普通", Color.Yellow, @"D:\DocToImg\picture\2.png");
                    new AQI_Table(LevelType.L3, 101, 150, 0.071m, 0.085m, 0.125m, 0.164m, 35.5m, 54.4m, 126m, 254m, 9.5m, 12.4m, 76m, 185m, null, null, 101m, 360m, "對敏感族群\n不健康", Color.Orange, @"D:\DocToImg\picture\3.png");
                    new AQI_Table(LevelType.L4, 151, 200, 0.086m, 0.105m, 0.165m, 0.204m, 54.5m, 150.4m, 255m, 354m, 12.5m, 15.4m, 186m, 304m, 186m, 304m, 361m, 649m, "對所有族群\n不健康", Color.Red, @"D:\DocToImg\picture\4.png");
                    new AQI_Table(LevelType.L5, 201, 300, 0.106m, 0.200m, 0.205m, 0.404m, 150.5m, 250.4m, 355m, 424m, 15.5m, 30.4m, null, null, 305m, 604m, 650m, 1249m, "非常不健康", Color.Purple, @"D:\DocToImg\picture\5.png");
                    new AQI_Table(LevelType.L6, 300, 400, null, null, 0.405m, 0.504m, 250.5m, 350.4m, 425m, 504m, 30.5m, 40.4m, null, null, 605m, 804m, 1250m, 1649m, "危害", Color.DarkRed, @"D:\DocToImg\picture\6.png");
                    new AQI_Table(LevelType.L7, 400, 500, null, null, 0.505m, 0.604m, 350.5m, 500.4m, 505m, 604m, 40.5m, 50.4m, null, null, 805m, 1004m, 1650m, 2049m, "危害", Color.DarkRed, @"D:\DocToImg\picture\7.png");
                }

                return table;



            }


            public static void CalcAQI(this List<AQI_Table> airQualityTable,
              decimal O3_8H_C,
              decimal O3_1hr,
              decimal PM25_C,
              decimal PM10_C,
              decimal CO_8H_C,
              decimal SO2_24H_C,
              decimal NO2_1hr,
              out int AQI,
              out PollutantType[] pollutantTypes)
            {
                //汙染物陣列
                var pollutantList = new List<Tuple<PollutantType, decimal>>
    {
        new Tuple<PollutantType, decimal>(
            PollutantType.O3_8hr, O3_8H_C),
        new Tuple<PollutantType, decimal>(
            PollutantType.O3_1hr, O3_1hr),
        new Tuple<PollutantType, decimal>(
            PollutantType.PM2_5, PM25_C),
        new Tuple<PollutantType, decimal>(
            PollutantType.PM10, PM10_C),
        new Tuple<PollutantType, decimal>(
            PollutantType.CO_8hr, CO_8H_C),
        new Tuple<PollutantType, decimal>(
            PollutantType.SO2_1hr, SO2_24H_C),
        new Tuple<PollutantType, decimal>(
            PollutantType.NO2_1hr, NO2_1hr),
    };


                var pollutantRowList = pollutantList.Select(it =>
                {
                    //產生可動態取得 low、high 的表達式樹
                    var pollutantName = it.Item1.ToString();
                    var type = typeof(AQI_Table);
                    var itParam = Expression.Parameter(type, "it");
                    var lowGetter = Expression.Property(itParam,
                        type.GetProperty($"{pollutantName}_low"));
                    var highGetter = Expression.Property(itParam,
                        type.GetProperty($"{pollutantName}_hight"));
                    var getLow = Expression.Lambda<Func<AQI_Table, decimal?>>(
                        lowGetter, itParam).Compile();
                    var getHigh = Expression.Lambda<Func<AQI_Table, decimal?>>(
                        highGetter, itParam).Compile();

                    var pollutantType = it.Item1;
                    var C = it.Item2;

                    //查表
                    var row = airQualityTable
                        .Where(itt => C >= getLow(itt) && C <= getHigh(itt))
                        .FirstOrDefault();

                    //查不到回傳 null
                    return row == null ? null : new
                    {
                        pollutantType = pollutantType,
                        row = row,
                        C = C,
                        Clow = getLow(row).Value,
                        Chigh = getHigh(row).Value,
                        Ilow = row.AQI_low,
                        Ihigh = row.AQI_hight,
                    };
                });

                //IAQI 計算公式
                var calc = (Func<decimal, decimal, decimal, int, int, int>)
                    ((C, Clow, Chigh, Ilow, Ihigh) =>
                    {
                        return (int)Math.Ceiling(
                    (Ihigh - Ilow) / (Chigh - Clow) * (C - Clow) + Ilow);
                    });

                //計算 IAQI
                var IAQI = pollutantRowList.Where(it => it != null)
                    .Select(it => new
                    {
                        pollutantType = it.pollutantType,
                        IAQI = calc(it.C, it.Clow, it.Chigh, it.Ilow, it.Ihigh),
                    })
                    .ToList();

                //算出最大值
                var max = IAQI.Max(it => it.IAQI);

                //回傳結果
                AQI = max;
                //指標汙染物可以有多個
                pollutantTypes = IAQI
                    .Where(it => it.IAQI == max)
                    .Select(it => it.pollutantType)
                    .ToArray();
            }
        }

        public static void AQI()
        {

            var O3_8H_C = get_O3_8H_average();
            var CO_8H_C = get_CO_8H_average();
            int PM25_24H_C = get_PM25_average();
            var PM10_24H_C = get_PM10_average();

            var pollutantTypes = null as PollutantType[];
            var table = AQI_Table_Ex.Create();

            var AQI = table.CalcAQI(38m * 1000, 21m * 1000, 18m, 34m, 0.30m, 1.8m,
        5.5m);


            return AQI;

        }

    }

https://ithelp.ithome.com.tw/upload/images/20180730/20109425Mcc2CKv6OW.jpg
https://ithelp.ithome.com.tw/upload/images/20180730/20109425Zi7wEyAVoB.jpg
https://ithelp.ithome.com.tw/upload/images/20180730/20109425JghyOqbkKU.jpg

大大可以幫我Help嗎./images/emoticon/emoticon06.gif

ted8224 iT邦新手 5 級 ‧ 2018-07-30 11:31:20 檢舉

後面您之前說的那一段 塞移動平均這段,因為是把算出來後的移動平均數值塞進去,畢竟是活的
下面我新增一些code
當然蝌蚪部分還是如上圖所示
/images/emoticon/emoticon06.gif

 public static double AQI()
        {
            
            string sq1 = @"SELECT TOP 1 *** FROM ** WHERE *** ORDER BY M_DateTime DESC  "; //O3臭氧  小時濃度
            string sq2 = @"SELECT TOP 1 *** FROM *** WHERE **** ORDER BY M_DateTime DESC  "; //SO2  小時濃度
            string sq3 = @"SELECT TOP 1 **** FROM *** WHERE **** ORDER BY M_DateTime DESC  "; //NO2 小時濃度
            DataTable dt = SqlCommand(sq1);
            DataTable dt2 = SqlCommand(sq2);
            DataTable dt3 = SqlCommand(sq3);



            var O3_8H_C = get_O3_8H_average();
            var CO_8H_C = get_CO_8H_average();
            int PM25_24H_C = get_PM25_average();
            var PM10_24H_C = get_PM10_average();

            var pollutantTypes = null as PollutantType[];
            var table = AQI_Table_Ex.Create();

           
            var AQI = table.CalcAQI(dt, dt2, dt3, CO_8H_C, PM25_24H_C,PM10_24H_C ,
            O3_8H_C);

            dt.Dispose();
            dt2.Dispose();
            dt3.Dispose();



            return AQI;

        }

重新開了一個 Winform 專案,結構如下。
https://ithelp.ithome.com.tw/upload/images/20180730/201068653RHrFVdf5A.jpg

LevelType

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AQI
{
    /// <summary>
    /// AQI 等級
    /// </summary>
    public enum LevelType
    {
        L1 = 1,
        L2,
        L3,
        L4,
        L5,
        L6,
        L7,
    }
}

PollutantType

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AQI
{
    /// <summary>
    /// 汙染物類型
    /// </summary>
    public enum PollutantType
    {
        O3_8hr,
        O3_1hr,
        PM2_5,
        PM10,
        CO_8hr,
        SO2_1hr,
        SO2_8hr,
        NO2_1hr
    }
}

AQI_Table

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace AQI
{
    /// <summary>
    /// 空氣品質指標對照表
    /// </summary>
    public class AQI_Table
    {
        public decimal? O3_1hr_low { get; set; }
        public decimal? O3_1hr_hight { get; set; }
        public decimal? O3_8hr_low { get; set; }
        public decimal? O3_8hr_hight { get; set; }
        public decimal? SO2_1hr_low { get; set; }
        public decimal? SO2_1hr_hight { get; set; }
        public decimal? SO2_8hr_low { get; set; }
        public decimal? SO2_8hr_hight { get; set; }
        public decimal? CO_8hr_low { get; set; }
        public decimal? CO_8hr_hight { get; set; }
        public decimal? NO2_1hr_low { get; set; }
        public decimal? NO2_1hr_hight { get; set; }
        public decimal? PM2_5_low { get; set; }
        public decimal? PM2_5_hight { get; set; }
        public decimal? PM10_low { get; set; }
        public decimal? PM10_hight { get; set; }
        public int AQI_low { get; set; }
        public int AQI_hight { get; set; }
        public LevelType LevelType { get; set; }
        public string Text { get; set; }
        public Color Color { get; set; }
        public string PicPath { get; set; }
    }
}

AQI_Table_Ex

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Drawing;

namespace AQI
{
    public static class AQI_Table_Ex
    {
        /// <summary>
        /// 產生空氣品質指標對照表資料
        /// </summary>
        /// <returns></returns>
        public static List<AQI_Table> Create()
        {
            var table = new List<AQI_Table>
            {
                new AQI_Table
                {
                    LevelType = LevelType.L1,   
                    AQI_low = 0,
                    AQI_hight = 50,
                    O3_8hr_low = 0.000m,
                    O3_8hr_hight = 0.054m,
                    O3_1hr_low = null,
                    O3_1hr_hight = null,
                    PM2_5_low = 0.0m,
                    PM2_5_hight = 15.4m,
                    PM10_low = 0m,
                    PM10_hight = 54m,
                    CO_8hr_low = 0m,
                    CO_8hr_hight = 4.4m,
                    SO2_1hr_low = 0m,
                    SO2_1hr_hight = 35m,
                    SO2_8hr_low = null,
                    SO2_8hr_hight = null,
                    NO2_1hr_low = 0m,
                    NO2_1hr_hight = 53m,
                    Text =  "良好",
                    Color = Color.Green,
                    PicPath = "picture1.png",
                },
                new AQI_Table
                {
                    LevelType = LevelType.L2,
                    AQI_low = 51,
                    AQI_hight = 100,
                    O3_8hr_low = 0.055m,
                    O3_8hr_hight = 0.070m,
                    O3_1hr_low = null,
                    O3_1hr_hight = null,
                    PM2_5_low = 15.5m,
                    PM2_5_hight = 35.4m,
                    PM10_low = 55m,
                    PM10_hight = 125m,
                    CO_8hr_low = 4.5m,
                    CO_8hr_hight = 9.4m,
                    SO2_1hr_low = 36m,
                    SO2_1hr_hight = 75m,
                    SO2_8hr_low = null,
                    SO2_8hr_hight = null,
                    NO2_1hr_low = 54m,
                    NO2_1hr_hight = 100m,
                    Text =  "普通",
                    Color = Color.Yellow,
                    PicPath = "picture2.png",
                },
                new AQI_Table
                {
                    LevelType = LevelType.L3,
                    AQI_low = 101,
                    AQI_hight = 150,
                    O3_8hr_low = 0.071m,
                    O3_8hr_hight = 0.085m,
                    O3_1hr_low = 0.125m,
                    O3_1hr_hight = 0.164m,
                    PM2_5_low = 35.5m,
                    PM2_5_hight = 54.4m,
                    PM10_low = 126m,
                    PM10_hight = 254m,
                    CO_8hr_low = 9.5m,
                    CO_8hr_hight = 12.4m,
                    SO2_1hr_low = 76m,
                    SO2_1hr_hight = 185m,
                    SO2_8hr_low = null,
                    SO2_8hr_hight = null,
                    NO2_1hr_low = 101m,
                    NO2_1hr_hight = 360m,
                    Text =  "對敏感族群\n不健康",
                    Color = Color.Orange,
                    PicPath = "picture3.png",
                },
                new AQI_Table
                {
                    LevelType = LevelType.L4,
                    AQI_low = 151,
                    AQI_hight = 200,
                    O3_8hr_low = 0.086m,
                    O3_8hr_hight = 0.105m,
                    O3_1hr_low = 0.165m,
                    O3_1hr_hight = 0.204m,
                    PM2_5_low = 54.5m,
                    PM2_5_hight = 150.4m,
                    PM10_low = 255m,
                    PM10_hight = 354m,
                    CO_8hr_low = 12.5m,
                    CO_8hr_hight = 15.4m,
                    SO2_1hr_low = 186m,
                    SO2_1hr_hight = 304m,
                    SO2_8hr_low = 186m,
                    SO2_8hr_hight = 304m,
                    NO2_1hr_low = 361m,
                    NO2_1hr_hight = 649m,
                    Text =  "對所有族群\n不健康",
                    Color = Color.Red,
                    PicPath = "picture4.png",
                },
                new AQI_Table
                {
                    LevelType = LevelType.L5,
                    AQI_low = 201,
                    AQI_hight = 300,
                    O3_8hr_low = 0.106m,
                    O3_8hr_hight = 0.200m,
                    O3_1hr_low = 0.205m,
                    O3_1hr_hight = 0.404m,
                    PM2_5_low = 150.5m,
                    PM2_5_hight = 250.4m,
                    PM10_low = 355m,
                    PM10_hight = 424m,
                    CO_8hr_low = 15.5m,
                    CO_8hr_hight = 30.4m,
                    SO2_1hr_low = null,
                    SO2_1hr_hight = null,
                    SO2_8hr_low = 305m,
                    SO2_8hr_hight = 604m,
                    NO2_1hr_low = 650m,
                    NO2_1hr_hight = 1249m,
                    Text =  "非常不健康",
                    Color = Color.Purple,
                    PicPath = "picture5.png",
                },
                new AQI_Table
                {
                    LevelType = LevelType.L6,
                    AQI_low = 300,
                    AQI_hight = 400,
                    O3_8hr_low = null,
                    O3_8hr_hight = null,
                    O3_1hr_low = 0.405m,
                    O3_1hr_hight = 0.504m,
                    PM2_5_low = 250.5m,
                    PM2_5_hight = 350.4m,
                    PM10_low = 425m,
                    PM10_hight = 504m,
                    CO_8hr_low = 30.5m,
                    CO_8hr_hight = 40.4m,
                    SO2_1hr_low = null,
                    SO2_1hr_hight = null,
                    SO2_8hr_low = 605m,
                    SO2_8hr_hight = 804m,
                    NO2_1hr_low = 1250m,
                    NO2_1hr_hight = 1649m,
                    Text =  "危害",
                    Color = Color.DarkRed,
                    PicPath = "picture6.png",
                },
                new AQI_Table
                {
                    LevelType = LevelType.L7,
                    AQI_low = 400,
                    AQI_hight = 500,
                    O3_8hr_low = null,
                    O3_8hr_hight = null,
                    O3_1hr_low = 0.505m,
                    O3_1hr_hight = 0.604m,
                    PM2_5_low = 350.5m,
                    PM2_5_hight = 500.4m,
                    PM10_low = 505m,
                    PM10_hight = 604m,
                    CO_8hr_low = 40.5m,
                    CO_8hr_hight = 50.4m,
                    SO2_1hr_low = null,
                    SO2_1hr_hight = null,
                    SO2_8hr_low = 805m,
                    SO2_8hr_hight = 1004m,
                    NO2_1hr_low = 1650m,
                    NO2_1hr_hight = 2049m,
                    Text =  "危害",
                    Color = Color.DarkRed,
                    PicPath = "picture7.png",
                },
            };
            return table;
        }
        
        /// <summary>
        /// 計算 AQI
        /// </summary>
        public static int CalcAQI(this List<AQI_Table> airQualityTable, 
            decimal? O3_8hr = null, 
            decimal? O3_1hr = null, 
            decimal? PM2_5 = null, 
            decimal? PM10 = null, 
            decimal? CO_8hr = null, 
            decimal? SO2_1hr = null, 
            decimal? NO2_1hr = null)
        {
            //汙染物陣列
            var pollutantList = new List<Tuple<PollutantType, decimal>>();
            if (O3_8hr.HasValue)
                pollutantList.Add(new Tuple<PollutantType, decimal>
                    (PollutantType.O3_8hr, O3_8hr.Value));
            if (O3_1hr.HasValue)
                pollutantList.Add(new Tuple<PollutantType, decimal>
                    (PollutantType.O3_1hr, O3_1hr.Value));
            if (PM2_5.HasValue)
                pollutantList.Add(new Tuple<PollutantType, decimal>
                    (PollutantType.PM2_5, PM2_5.Value));
            if (PM10.HasValue)
                pollutantList.Add(new Tuple<PollutantType, decimal>
                    (PollutantType.PM10, PM10.Value));
            if (CO_8hr.HasValue)
                pollutantList.Add(new Tuple<PollutantType, decimal>
                    (PollutantType.CO_8hr, CO_8hr.Value));
            if (SO2_1hr.HasValue)
                pollutantList.Add(new Tuple<PollutantType, decimal>
                    (PollutantType.SO2_1hr, SO2_1hr.Value));
            if (NO2_1hr.HasValue)
                pollutantList.Add(new Tuple<PollutantType, decimal>
                    (PollutantType.NO2_1hr, NO2_1hr.Value));
            
            var pollutantRowList = pollutantList.Select(it =>
            {
                //產生可動態取得 low、high 的表達式樹
                var pollutantName = it.Item1.ToString();
                var type = typeof(AQI_Table);
                var itParam = Expression.Parameter(type, "it");
                var lowGetter = Expression.Property(itParam, type.GetProperty($"{pollutantName}_low"));
                var highGetter = Expression.Property(itParam, type.GetProperty($"{pollutantName}_hight"));
                var getLow = Expression.Lambda<Func<AQI_Table, decimal?>>(lowGetter, itParam).Compile();
                var getHigh = Expression.Lambda<Func<AQI_Table, decimal?>>(highGetter, itParam).Compile();

                var pollutantType = it.Item1;
                var C = it.Item2;

                //查表
                var row = airQualityTable
                    .Where(itt => C >= getLow(itt) && C <= getHigh(itt))
                    .FirstOrDefault();
                
                //查不到回傳 null
                return row == null ? null : new
                {
                    pollutantType = pollutantType,
                    row = row,
                    C = C,
                    Clow = getLow(row).Value,
                    Chigh = getHigh(row).Value,
                    Ilow = row.AQI_low,
                    Ihigh = row.AQI_hight,
                };
            });

            //IAQI 計算公式
            var calc = (Func<decimal, decimal, decimal, int, int, int>)((C, Clow, Chigh, Ilow, Ihigh) =>
            {
                return (int)Math.Ceiling((Ihigh - Ilow) / (Chigh - Clow) * (C - Clow) + Ilow);
            });

            //計算 IAQI
            var IAQI = pollutantRowList.Where(it => it != null)
                .Select(it => new
                {
                    pollutantType = it.pollutantType,
                    IAQI = calc(it.C, it.Clow, it.Chigh, it.Ilow, it.Ihigh),
                });

            //算出最大值
            return IAQI.Max(it => it.IAQI);
        }
    }
}

Form1

using AQI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AQI計算
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var O3_8hr = get_O3_8hr_average();
            var O3_1hr = get_O3_1hr_average();
            var PM2_5 = get_PM2_5_average();
            var PM10 = get_PM10_average();
            var CO_8hr = get_CO_8hr_average();
            var SO2_1hr = get_SO2_1hr_average();
            var NO2_1hr = get_NO2_1hr_average();

            var table = AQI_Table_Ex.Create();

            //計算 AQI
            var AQI = table.CalcAQI(
                O3_8hr: O3_8hr,
                O3_1hr: O3_1hr,
                PM2_5: PM2_5,
                PM10: PM10,
                CO_8hr: CO_8hr,
                SO2_1hr: SO2_1hr,
                NO2_1hr: NO2_1hr);

            //取得顏色圖片等等資訊
            var item = table
                .Where(it => it.AQI_low <= AQI && it.AQI_hight >= AQI)
                .FirstOrDefault();
        }

        public decimal get_O3_8hr_average()
        {
            //需實作
            return default(decimal);
        }
        public decimal get_O3_1hr_average()
        {
            //需實作
            return default(decimal);
        }
        public decimal get_PM2_5_average()
        {
            //需實作
            return default(decimal);
        }
        public decimal get_PM10_average()
        {
            //需實作
            return default(decimal);
        }
        public decimal get_CO_8hr_average()
        {
            //需實作
            return default(decimal);
        }
        public decimal get_SO2_1hr_average()
        {
            //需實作
            return default(decimal);
        }
        public decimal get_NO2_1hr_average()
        {
            //需實作
            return default(decimal);
        }
    }
}
ted8224 iT邦新手 5 級 ‧ 2018-07-30 16:59:28 檢舉

/images/emoticon/emoticon08.gif
大大感謝, 我試試看..

大概就是
把class 不要塞在同一個.cs 檔

創造很多個弄成各項類別,和函式

在從最原本Windowfrom.cs
去讀其他的.cs 檔
其他的.cs 資料餵入 Windowfrom.cs

把要附加的功能等等,比如連線資料庫段,把數值丟到excel欄位等等..
都寫在Windowfrom.cs裡

謝謝大大/images/emoticon/emoticon42.gif

哈哈哈,您說的很對!!!
其實也就是您一開始的疑問。

如何做成 function,如何綁成 class。
ted8224 iT邦新手 5 級 ‧ 2018-07-31 09:27:11 檢舉

@fy 大大謝謝您
恩...怎辦 想問你一個問題 Omg
https://ithelp.ithome.com.tw/upload/images/20180731/20109425MMnCrG0cVf.jpg

怎辦
我最新版VS2017 更新到 8月了 /images/emoticon/emoticon02.gif

我C# 升級到 7.2..了說

說小括號無效
https://ithelp.ithome.com.tw/upload/images/20180731/20109425XFtZQLCqH8.jpg

括號, 逗號,分號 我都試過 ,刪除 重新排列位置../images/emoticon/emoticon02.gif

最後一個參數多了逗號。

ted8224 iT邦新手 5 級 ‧ 2018-07-31 13:17:37 檢舉

大大 後面 接的型別是不是 只能 Int 型別?

對,AQI 是整數,我用 int 當回傳值。

ted8224 iT邦新手 5 級 ‧ 2018-07-31 14:13:08 檢舉

可是後面這段

var AQI = table.CalcAQI(
                        O3_8hr: O3_8H_C,
                        O3_1hr: dt6, //小時濃度
                        PM2_5: PM25_24H_C ,
                        PM10: PM10_24H_C,
                        CO_8hr: CO_8H_C,
                        SO2_1hr: dt8 ,  //小時濃度
                        NO2_1hr: dt9 ) ;

其中 幾項是 double 型別..

在那之前 使用大大 您之前用的語法,把移動平均都改成都改成int 型別嗎?

可是我是覺得 有點怪怪 因為移動平均, 是有小數點的說..
那至於上面 dt8,9 之類
是從資料庫接數據來的,表上寫小時平均,沒錯的話,因該是小時濃度

移動平均那邊不用改,參數是 double 沒錯 (我是用 decimal),回傳(AQI)是 int,不衝突。

ted8224 iT邦新手 5 級 ‧ 2018-07-31 14:47:56 檢舉

https://ithelp.ithome.com.tw/upload/images/20180731/20109425pdzSYKaoEQ.jpg

https://ithelp.ithome.com.tw/upload/images/20180731/20109425d5QLq88UyQ.jpg

大大不好意思.. 可是為什麼會 紅色蝌蚪阿.. Help /images/emoticon/emoticon06.gif
照理說這樣因該沒問題啊

我是用 decimal 吧,哈哈哈

ted8224 iT邦新手 5 級 ‧ 2018-07-31 15:31:14 檢舉

沒事了,要改一下 型別.. 謝謝大大/images/emoticon/emoticon08.gif

ted8224 iT邦新手 5 級 ‧ 2018-08-01 10:13:20 檢舉

不好意思
@fy 大大 請問
https://ithelp.ithome.com.tw/upload/images/20180801/20109425cqrBsNsp1o.jpg
https://ithelp.ithome.com.tw/upload/images/20180801/20109425j9P5meDoJH.png

可是後面數值,好像有進入
卻不能轉換

可以Help 嗎?/images/emoticon/emoticon06.gif

這樣看不太出來,要先把 try catch 拿掉看出錯在哪一段程式。

ted8224 iT邦新手 5 級 ‧ 2018-08-01 14:29:05 檢舉

就是那一大段 測出來Bug 是白色圈起來那一大段 進去不了AQI_Table_Ex.CS

類型轉換有問題 , 可是理論上 因該OK

/images/emoticon/emoticon06.gif

@f 大大 Help../images/emoticon/emoticon02.gif

好像是因為,DataTable 不能轉型成 Decimal,要先把 dt6 算出來。

Convert.ToDecimal(dt6);
ted8224 iT邦新手 5 級 ‧ 2018-08-01 15:38:44 檢舉

/images/emoticon/emoticon08.gif
@f 大大 我成功了!!!

感謝./images/emoticon/emoticon42.gif

/images/emoticon/emoticon34.gif

0
小魚
iT邦大師 1 級 ‧ 2018-07-20 08:20:06

第二段程式碼不用判斷了,
number >= 50成立後面都不會執行了,
所以永遠都是 良好,
如果從後面的條件往回判斷倒是可以,
這你要自己思考一下...
另外"良好"本身就是字串了,不需要再ToString了,
是不會錯誤只是多此一舉。

ted8224 iT邦新手 5 級 ‧ 2018-07-20 08:44:55 檢舉

不是 小魚大 .. 我想到地目前狀況 寫到那樣,剩下的,數學公式,要寫成函數,和一些 上面那一張大表格,寫成函數,我不太會

小魚 iT邦大師 1 級 ‧ 2018-07-20 12:00:16 檢舉

其實我不知道你的需求是什麼,
如同 rainbowrain 大大所說的那樣,
不過我提出來的那個是有問題的...

ted8224 iT邦新手 5 級 ‧ 2018-07-21 14:07:07 檢舉

恩恩 那邊改好了... 謝謝@小魚大

我要發表回答

立即登入回答