2019年8月14日 星期三

C# struct 是傳值(value)還傳參(reference)?為了效能我要加ref嗎?


答案是惱人,是也不是。
利用  「GetType().IsValueType」可以檢查物件是否為「實數型別」。
所以檢測出,struct 物件是實數型別。
但傳遞時,卻不是複製一樣的物件,而是傳參,而這傳參是一種唯讀概念。也就是在函式中改動也不會影響原struct物件的內容。
總之,C#把很多物件都作了優化,把許多類別物件都變成傳參,唯有當你修改時才會複製成新物件。

所以函式的參數如果有struct時,用不用ref效能是差不了太多。反而用了ref很容易一個不小心改了資料還沒發現。如果真的很想知道差異,我作了測試。發現使用ref的效能是好上10%,但這差異是跑了3千萬次後,少了0.29秒。
也就是函式帶struct參數並使用ref,每次可省0.00000967毫秒
結論:函式帶struct參數時,如果不會更動資料,就不要加ref。一來用物理性防呆,二來簡單


函式範例樣子:
使用ref的函式:public string 我的函式(ref 結構資料 A)
未使用ref的函式:public string 我的函式(結構資料 A)






函式
        static public bool 是否為實值型別(object  物件)
        {
            return 物件.GetType().IsValueType;
        }

參考資料
C# 傳值Call by value、參考Call by Reference 與相等比較
[C#][筆記] Value Type (實值型別) vs. Reference Type (參考型別)
作法:了解傳遞結構和傳遞類別參考給方法之間的差異
[沒有蠢問題] c# 如何分辨 實值型別,參考型別
Type.IsValueType Property

2019年8月6日 星期二

Try Catch 效能耗損測試

總結:
直接說結果,是有差別。證明try是會額外耗損資源。多少呢?少到你不會在乎,9億次只額外耗損不到19秒。平均使用一個try額外耗損0.000021毫秒(條件:未觸發catch)
建議:程式不要當機(crash)才是最重要的事,所以別因微不足道的耗損而刻意不使用或關閉。
當掉才是最該避免的事


提醒:只要跑進catch(異常發生)就一定會造成顯著的耗損
提外話:在跑程式時,我有發現一個現象,先執行for迴圈的比較吃虧。所以測試時我有作對調,外加Release+Debug版。所以執行四次。

說明:
執行次數:各自執行9000000*100=9億次
時間單位毫秒


  使用try 未使用try
測試1 6225 620
測試2 10228 6120
測試3 6173 624
測試4 9908 6673
     
加總 32534 14037

記錄圖:
看不懂很正常,因為只是給我自己作記錄用。







程式碼:
        private void 測試()
        {
            long T = 0;
            long T2 = 0;
            int A = 0;
            string B = "";
            System.Diagnostics.Stopwatch sw;
            System.Threading.Thread.Sleep(2000);
            for (int g = 1; g < 100; g++)
            {
                //無try
                A = 0;
                B = "";
                sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                for (int i = 0; i < 9000000; i++)
                {
                        A = i % 13;
                        A += 1;
                }
                sw.Stop();
                T2 += sw.ElapsedMilliseconds;
                //有try
                System.Threading.Thread.Sleep(1000);
                A = 0;
                B = "";
                sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                for (int i = 0; i < 9000000; i++)
                {
                    try
                    {
                        A = i % 13;
                        A += 1;
                    }
                    catch (Exception ex)
                    {
                        B = ex.Message;
                    }
                }
                sw.Stop();
                T += sw.ElapsedMilliseconds;
            }
            System.Threading.Thread.Sleep(1000);
            for (int g = 1; g < 100; g++)
            {
                //有try
                A = 0;
                B = "";
                sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                for (int i = 0; i < 9000000; i++)
                {
                    try
                    {
                        A = i % 13;
                        A += 1;
                    }
                    catch (Exception ex)
                    {
                        B = ex.Message;
                    }
                }
                sw.Stop();
                T += sw.ElapsedMilliseconds;
                //無try
                A = 0;
                B = "";
                sw = new System.Diagnostics.Stopwatch();
                sw.Start();
                for (int i = 0; i < 9000000; i++)
                {
                    A = i % 13;
                    A += 1;
                }
                sw.Stop();
                T2 += sw.ElapsedMilliseconds;

            }
            txtMsg.AppendText(Environment.NewLine +"使用Try:" + T.ToString());
            txtMsg.AppendText(Environment.NewLine + "未使用Try:" + T2.ToString());
        }

2019年8月5日 星期一

Visual Studio 自動列出成員,但無法按空白鍵自動帶出成員(反藍條)

導言:
有時寫程式寫一寫,突然visual studio無法使用空白鍵,自動完成成員。你大概知道又不小心按到什麼快捷鍵,但就是找不到關掉的地方。即使重啟VS也無效。真是惱人的方便,造成的不便。

Step 1:檢查自動列出成員功能
工具>選項>文字編輯器>C#>一般>陳述式完成>(勾選)自動列出成員。


Step 2:測試
看能否自動列出,和反藍。
有帶出自動,卻無法沒反藍,所以也就無法用空白鍵自動完成。



Step 3:
上方工具列區>右鍵>(勾選)文字編輯器介面



Step 4:
取消「在建議和標準完成模式之間切換(Crt+Alt+空白鍵)」

Step 5:完成
反藍出現了,代表空白鍵能作用了。


總結:
Visual Studio介面設計不佳,只要一急不小心手滑了一下,就把自動完成功能給關了都不知道。而快捷鍵(Crt+Alt+空白鍵)設定更是惱人,中英文切換不小心按快一點就又不明不白的關掉自動完成功能了。


參考資料:
[Visual Studio]需要手動打開提示碼嗎? 這裡教您如何打開自動列出成員。
Visual Studio 中的 Intellisense

2019年8月1日 星期四

收盤價與結算價不同?

收盤價:是指當日最後一筆的成交價


昨日結算價(報價軟體顯示的昨收):是指昨日最後一分鐘的加權平均數(取整數,捨小數)。


結算價=是指今日最後一分鐘的加權平均數(取整數,捨小數)。

開盤平價點=昨收價=昨日結算價


總結:
報價軟體為了方便,把昨日收盤價直接改成昨日結算價。導致許多程式定義時很亂。最好參照期交所定義的名稱來設定資料庫或程式名稱。


期貨相關名詞

股價指數-期貨
.臺股期貨=大台=TX
.小型臺指期貨=小台=MTX
.電子期貨=電子期=TE
.金融期貨=金融期=TF

股價指數-選擇權
.臺指選擇權=選擇權=TXO

股票期貨
.不是加權指數,是個股。一字之差「價」與「票」。


結算價:一般交易時段收盤前1分鐘內所有交易之成交量加權平均價(大台成交價✖成交量)
最後結算價:結算日收盤前30分鐘內「標的指數」之簡單算數平均數→大盤報價,非大台。


參考
期貨選擇權手冊.pdf




大台(臺股期貨)每日漲停價、跌停價 計算方式

導言:
這題難解之處在「關鍵字」很難找,答案是在《期交所》網站《臺灣證券交易所股價指數期貨契約》。找到「每日結算價」這關鍵字答案就差不多出來了

Step 1:每日結算價
定義:每日結算價原則上採當日一般交易時段收盤前1分鐘內所有交易之成交量加權平均價,若無成交價時,則依本公司「臺灣證券交易所股價指數期貨契約交易規則」訂定之

Step 2: 前30個交易日期貨每筆成交資料
位置:期交所>首頁 > 交易資訊 > 資料下載專區 > 交易資訊 > 期貨 > 前30個交易日期貨每筆成交資料 

提醒:注意下載日期和時間,當日的日盤交易(一般時段)資料要到18:40左右才會產出。如果太早下載會不完整。最佳防呆做法就是次日才下載前一個交易日的資料

Step 3:資料格式
格式:成交日期,商品代號,到期月份(週別),成交時間,成交價格,成交數量(B+S),近月價格,遠月價格,開盤集合競價 

篩出:
成交日期=前一個交易日
商品代號=TX
到期月份=操作的大台契約月份(ex:201908)

注意:有價差交易的資料要剔除

Step 4:昨日結算價
公式:昨日,一般交易時段,收盤前1分鐘內,所有交易之成交量加權平均價。
資料區間取:成交時間 134400~134500
計算方式:
昨日結算價_帶小數=sum(成交價格*成交數量)/成交數量,
昨日結算價=(int)昨日結算價_帶小數→只取整數,小數去除不計也不四捨五入。

提示:我是寫入資料庫去撈,所以才會出現sum()函式。
爭議:四捨五入至小數第二位,是期交所的共識法則。但這邊可能是例外

Step 5:今日漲停價
計算方式:昨日結算價✖1.1,取整數(直接去小數,沒有四捨五入,因為會超過10%。

C#程式碼
        public  int  計算當日價格上限(int 昨日結算價)
        {
            return (int)(昨日結算價 * 1.1);
        }

Step 5:今日跌停價
計算方式:昨日結算價✖0.9+1。(加1才能不會超出-10%。除非常好是整數)
C#程式碼
        public  int 計算當日價格下限_小數2位(double 昨日結算價_帶小數)
        {
            if ((昨日結算價_帶小數 * 0.9)%1)//如果剛好整數,就不用+1了
                return (int)(昨日結算價_帶小數 * 0.9);
            else
                return  (int)(昨日結算價 * 0.9) + 1;
        }

爭議:如果是取小數2位作判斷是否為整數(12345.0089在判斷視同12345)
C#程式碼
        public  int 計算當日價格下限_小數2位(int 昨日結算價)
        {
            //取2位小數作有效值
            int i計算 = (int)((昨日結算價 * 0.9)* 100);
            double d結果 = i計算 / 100.0;
            if (d結果%1)//如果剛好整數,就不用+1了
                return (int)(昨日結算價 * 0.9);
            else
                return  (int)(昨日結算價 * 0.9) + 1;
        }

Step 5:驗證一致《期貨每日交易行情下載
位置:期交所>首頁 > 交易資訊 > 交易資訊 > 期貨 > 期貨每日交易行情下載 
比對:結算價是否與期交所一致。




總結:
期交所的名詞常常跟生活用語不同,像「臺股期貨」一般人不會這樣叫,而用「大台」。而昨日結算價,直覺是昨收價。總之,要找出精確數值比預期的困難許多,每日限制±10%,一句話卻充滿著許多定義不明之處,必須慢慢測試才能與期交所公布的一致。


C# 四捨五入函式
        System.Math.Round(10736.79 , 0, MidpointRounding.AwayFromZero)

參考資料:
臺灣期貨交易所
C# 無條件進位,無條件捨去及四捨五入寫法

2019年6月16日 星期日

Android 封鎖簡訊 功能

導言:
預設的簡訊功能非常陽春,沒有擋簡訊功能。但現在病態多,尤其是廣告商,生兒子沒屁眼的人渣。無孔不入的丟簡訊給我。最近生氣了,抽空研究一下,沒想到google已提供了「Android Messages (訊息)」的程式,不是像Whoscall這種非google製作的軟體。

Step 1:google 標準說明
看完會不知所云,因為預設的「訊息功能」軟體,不是這邊說的「訊息」軟體。是不同東西




Step 2:下載《google messages》
在《Play 商店》輸入「訊息」,就找到了。但別點到「Messenger」那是Facebook的軟體。



Step 3:
選擇想封鎖的訊息>按住>上方會跳出選項>選封鎖圖示



Step 4:
封鎖並檢舉騷擾/廣告電話



總結:
google終於知道廣告簡訊多麼擾人了,才政策改變。做出可封鎖的軟體,不然簡訊這個洞長期被廣告商拿來用,真是不勝其擾。政府又很沒用,法律是禁止亂發廣告,但廣告商看準政府不會理會這種小事。
終於把畜牲們封鎖掉了,真是舒服。


2019年6月6日 星期四

完整複製資料庫(含資料結構)

導言:


Step 1:備份資料(來源)
1.[SSMS]>[資料庫]>右鍵>[工作]>[備份]
2.[備分資料庫]>[目的地]>[加入]>[確定]






Step 2:建新資料庫(目標)
[SSMS]>[資料庫]>右鍵>[新增資料庫]
注意:記得改路徑,不然預設位置會讓很難找。



Step 3:複製完整資料庫
1.[SSMS]>[資料庫]>[目標資料庫]>右鍵>[工作]>[還原]>[資料庫]
2.還原資料庫>裝置>[...]>找還剛作的備份檔>
3.




Step 4:發生錯誤
備份組包含現有的資料庫以外的資料庫備份。

Step 5:修改檔案
1.(主檔):[還原資料庫]>[檔案]>[還原為]>[...]
2.(記錄檔):[還原資料庫]>[檔案]>[還原為]>[...]

3.[還原資料庫]>[選項]>[還原選項]>[覆寫現有的資料庫],打勾。

4.[確定]


總結:
這方法解決了,單純匯出資料庫的問題,無法完整的複製表格結構,尤其是識別規格。



參考資料:
轉載:sql server完整複製資料庫

2019年6月1日 星期六

SQL Server Insert時如何取得識別值(id)

導言:
這問題困擾我很久,但因為沒有必要性所以沒有去研究。直到最近因為如果自製Primary key至少會需要16碼(yyyyMMssHHmmssff),而這不止醜還造成表單顯示太長一串。沒想到上網一查,居然早就有功能了,只是我一直沒研究。


Step 1:Sql Server提供的識別規格
這功能讓人愛不釋手,因為太放便了,但也是許多問題的來源。尤其是在複製資料時,一不小心個自動功能,會讓目標表的id跟原本的不一樣。但…實在太好用了。





Step2:最大問題新增時怎麼知道這識別值是多少呢?
正常 insert into 是有去無回的指令,除非錯誤,不然不會有回傳值。這不打緊因為寫程式習慣沒錯誤就是ok。但問題是我需要該識別值呀。查了網路文章,馬上有解。原來有這種語法!!

INSERT INTO Test ([name])
OUTPUT Inserted.id,Inserted.name
VALUES ('jack');

總結:
 好方便,也意識到我的技術已落後今日水準非常多了。 

參考:
SQL 下完 Insert Into 之後,取得剛剛 Insert 的欄位值 (指定返回欄位)

2019年5月28日 星期二

同伺服器下複製資料庫

導言:
這需求通常是把主資料庫的資料匯到測試資料庫,身為程式人員,直覺是把檔案(.mdf)複製改名就好。但SQL SERVER並不提供這麼直覺的方法。然後就很想用寫程式的方式來解缺,但比較簡單的做法是用SQL Server 提供的匯入匯出來完成。很不直覺,但操作最簡單。


Step 1:[問題]無法在附加資料庫時更改資料庫名稱




Step2:匯出資料
資料庫>右鍵>工作>匯出資料



Step3:歡迎使用 SQL Server匯入和匯出精靈

Step4:資料來源:SQL Server Native Client xx.oo




總結:
好的方法,常常就不是那麼直覺。我要複製資料庫,怎麼會用匯出?而想法不同結果卻一樣。邏輯推論的盲點。

SQL Server匯入匯出精靈 無法擷取資料表清單 ,登入逾時終止

導言:
這問題常出在,SQL Server Express版本。因為預設SQL Server伺服器名稱不需要加註\SQLEXPRESS。


Step 1:問題
在使用匯出資料功能時,發生無法登入目標主機。
[無法擷取資料表單。]
[登入逾時終止]


Step2:修改,伺服器名稱+\SQLEXPRESS



Step3:連通了


總結:
因為EXPRESS版免費,所以很多小地方就是讓你很不舒服。