發表文章

[Python] 關於 numpy 以及1~5維度的資料

  如題,由於在機器學習中,必定會遇到資料,例如: x_train = array([[0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], ..., [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.], [0., 0., 0., ..., 0., 0., 0.]], dtype=float32) 那個透過 numpy,可以得到 x_train.shape = (50000, 784) ,究竟 numpy, x_train 是什麼呢? 如何知道資料類型? 有哪些屬性? 有哪些方法? x_train 數據和其形狀 (50000, 784),這說明它是一個 NumPy 數組,通常用於深度學習和機器學習中的數據集表示。以下是對 x_train 的分析: ● x_train 是什麼? 類型:x_train 是一個 NumPy 數組(numpy.ndarray)。 數據形狀:它的形狀為 (50000, 784),這意味著這個數組有 50000 行和 784 列。在機器學習中,每一行(row)通常代表一個樣本,每一列(column)代表一個特徵。 ● 其中的數據代表什麼? 根據形狀,這個數組可能用於表示圖像數據集,其中每行(row)代表一個扁平化的圖像。例如,在手寫數字識別問題(如 MNIST 數據集)中,每個 28x28 像素的圖像被扁平化為一個長度為 784 的一維數組。 數據類型為 float32,這是深度學習中常用的數據類型,用於減少內存消耗並提高計算效率。 ● NumPy 數組的主要屬性: ndarray.shape:數組的各維度大小。 ndarray.size:數組中元素的總數。 ndarray.dtype:數組元素的數據類型。 ndarray.ndim:數組的維數。 ● NumPy 數組的常用方法: reshape:改變數組的形狀。 flatten 或 ravel:將多維數組降為一維。 transpose:轉置數組。 sum、mean、std 等:計算統計量。 max、min:尋找最大值和最小值。 import numpy as np # 假設 x_trai...

[IIS] 32位元應用程式,無故異常錯誤合輯

圖片
  由於維護IIS時,偶而會遇到無故異常事件,原因都是32位元應用程式導致的,以上記錄一下。 1. Crytal Report 的 log4net 錯誤 這個錯誤發生於32位元應用程式,將 32位元應用程式 改為 False。 2. [ODBC 驅動程式管理員] 找不到資料來源名稱且未指定預設的驅動程式 這個錯誤發生於32位元應用程式,將 32位元應用程式 改為 True。 ●總結: 如果有遇到本來正常,但是突然錯誤的狀況,那可能就是這個問題,改為 True, False 都試試看。

[Windows] 7-Zip解壓縮簡中檔名為亂碼

圖片
  解決7zip解壓縮亂碼問題。 下載7zip(這步就省略了。 https://www.7-zip.org/download.html ) 設定7zip環境變數(詳見下圖): C:\Program Files\7-Zip cmd cd到指定的目錄,輸入以下指令: 7z x 您的檔案.zip -mcp=936 參數: x => 代表解壓縮 您的檔案.zip => 檔名 -mcp=936 => 指定編碼為簡中 --簡中 936 --日文 932 --編碼可以參考:  https://www.wikiwand.com/en/Code_page#/DOS_code_pages 參考: https://tech.gjlmotea.com/2021/07/windows7-zip.html https://blog.csdn.net/u010348546/article/details/124087985

[AI] 歸一化 Normalization

圖片
  AI、深度學習領域很常見到 歸一化 ,之看都沒有很了解,故整理後簡單說明。 說明 : 歸一化是將數據按比例縮放到一個共同的範圍或分布內,以提高數據處理或模型學習的效率和效果。 目的 :   1.  提高算法效率 :在許多機器學習和數據分析算法中,如果數據特徵的尺度差異很大,會導致學習過程緩慢甚至不收斂。歸一化通過將所有特徵縮放到相同的尺度範圍內,有助於加速學習過程。   2.  提高模型性能 :對於一些基於距離的算法(如K近鄰、K-均值聚類等),特徵的尺度差異會直接影響距離的計算,進而影響模型的性能。通過歸一化,可以確保不同尺度的特徵對模型的貢獻是均衡的。   3.  避免數值問題 :在處理包含很大或很小數值的數據時,可能會遇到數值溢出或下溢的問題。歸一化有助於將數據縮放到一個合適的範圍內,減少這類問題。   4.  滿足模型假設 :某些統計模型和算法需要數據符合特定分布(如正態分布),或者需要特徵之間具有相似的尺度。歸一化可以是達到這些前提假設的一種方法。 常見的歸一化方法 : 1. 最小-最大歸一化 (Min-Max Normalization) 2. Z得分歸一化 (Z-Score Normalization) 3. 小數定標歸一化 (Decimal Scaling Normalization) 結論: 歸一化並沒有指定的公式,但有常見的公式。主要是看當下的場景去定義適合的歸一化。

[JS] 浮點數精度問題

  使用JS計算時,通常都會遇到浮點數的精度問題,例如以下: // 使用js浮點數相加: // 0.1 + 0.2 = 0.30000000000000004 // 0.33 * 10 = 3.3000000000000003 解決的方法: // 解法: parseFloat (( 0.1 + 0.2 ).toPrecision( 12 )) -- result: 0.3 parseFloat (( 0.33 * 10 ).toPrecision( 12 )) -- result: 3.3 // 可以封裝成方法 function strip ( num, precision = 12 ) { return + parseFloat (num.toPrecision(precision)); } 那為什麼要 toPrecision(12) 呢? 目的是要取精度,如果把精度提高,這樣又會現出原形了,所以12是個常見的經驗值,可以依照現況調整。 // 精度提高結果 parseFloat (( 0.1 + 0.2 ).toPrecision( 18 )) -- result: 0.30000000000000004 parseFloat (( 0.33 * 10 ).toPrecision( 18 )) -- result: 3.3000000000000003 實際背後的原因 就是 JavaScript 中所有數位包括整數和小數都只有一種類型 — Number。 它的實現遵循 IEEE 754 標準,使用 64 位固定長度來表示,也就是標準的 double 雙精度浮點數(相關的還有 float 32 位單精度)。: // 0.1 和 0.2 都轉化成二進位後再進行運算 0.0001100110011001100110011001100110011001100110011001101 + 0.001100110011001100110011001100110011001100110011001101 = 0.0100110011001100110011001100110011001100110011001100111 // 轉成十進位正好是0.300000000000000004 詳細說明可以詳閱:  ht...

[AI] 深度學習模型 vs 傳統機器學習模型

  深度學習模型和傳統機器學習模型主要的區別在於它們的架構、處理數據的方式、學習能力和應用場景。 以下是兩者之間的幾個主要區別以及各自的五大經典模型: 1. 模型架構: 深度學習:通常由多層(深層)的人工神經網絡構成,這些層次可以自動學習數據的高階特徵。 傳統機器學習:往往依賴於手工特徵提取和簡單的算法,如線性模型,不需要過於複雜的架構。 2. 數據處理能力: 深度學習:擅長處理大規模數據集,特別是高維度和非結構化數據(如圖像、聲音和文本)。 傳統機器學習:更適合處理小到中等規模的數據集,且通常需要結構化數據。 3. 特徵學習: 深度學習:可以自動從數據中學習特徵,減少了對專業知識的依賴。 傳統機器學習:大多數情況下需要手動設計特徵,這要求對數據的專業知識。 4. 計算要求: 深度學習:計算密集型,需要強大的硬件支持(如GPU)。 傳統機器學習:通常計算需求較低,可以在沒有專門硬件的情況下運行。 5. 應用場景: 深度學習:非常適合複雜問題和大規模數據分析,如自動駕駛、語音識別和自然語言處理。 傳統機器學習:適用於預測分析、分類問題和回歸分析,如信用評分、客戶分類。 五大經典深度學習模型 卷積神經網絡(CNNs):廣泛用於圖像和視頻處理。 遞歸神經網絡(RNNs):適用於處理序列數據,如時間序列分析和語言模型。 長短期記憶網絡(LSTMs):一種特殊類型的RNN,專門處理長序列數據。 生成對抗網絡(GANs):用於生成接近真實的圖像、聲音和視頻數據。 Transformer模型:在自然語言處理領域,特別是在翻譯和文本生成中表現出色。 五大經典傳統機器學習模型 線性回歸(Linear Regression):用於預測和趨勢分析。 支持向量機(SVMs):廣泛應用於分類問題。 決策樹(Decision Trees):用於分類和回歸任務,易於理解和實現。 隨機森林(Random Forests):一種基於決策樹的強大集成學習方法。 K-最近鄰(K-NN):一種簡單但強大的分類和回歸算法。 這些模型各有其應用的領域和優勢,選擇合適的模型通常基於特定的應用需求和數據類型。

[SQL] 查找&修改 Oracle tnsnames.ora

圖片
 如題,公司內當外部DB有改連線資訊時,對接的Server也需要調整,簡單整理如下。 1. win + R 輸入 regedit 開啟 登陸編輯程式,找到 HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE 2. 在該路徑後面應該可以找到 NETWORK\ADMIN\tnsnames.ora 3 . 依照外部資訊修改 tnsnames.ora 即可。

[Windows] 透過 Domain Controller 取得 LDAP

如題,在大公司使用AD驗證是很常見的,且當有多個子公司時,LDAP就有可能會更換,此時突然變動就沒法登入了,確實有點麻煩,解決方式如下。 // 假設你的 DC如下 // DC = "dc=DC01,dc=yourdomain,dc=intra"; // 於 CMD 輸入以下指令 nltest /dsgetdc:DC01.yourdomain.intra // 結果會如下: DC: \\DC01.yourdomain.intra Address: \\10.1.1.10 Dom Guid: ... Dom Name: yourdomain.intra Forest Name: yourdomain.intra Flags: ... // 而 Address 就是LDAP,Port通常為389。 // C#程式就會如下... DC = "dc=DC01,dc=yourdomain,dc=intra"; LDAP = "LDAP://10.1.1.10:389";

[Note] 公司常見的書信結尾

 紀錄公司內部,常見的書信結尾。 結尾用語,用以下來簡單說明: Best wishes > Warm regards > Kind regards > Best regards > Sincerely          (最親切)                      (最正式) 版本一:最中性正式,適用所有場合 若有未盡之處,敬請不吝指正,感謝您的寶貴意見。 Sincerely, John Wall 版本二:偏禮貌謙虛,對長官或客戶 如有疏漏之處,尚祈賜教。感謝撥冗閱覽。 Sincerely, John Wall 版本三:簡潔專業,給同事或跨部門 若有任何需補充處,歡迎隨時告知。謝謝。 Kind regards, John Wall 版本四:中英對照混排,跨國溝通首選 若有未盡周延之處,敬請不吝指教,謝謝! Should you have any feedback or suggestions, please feel free to let me know. Warm regards, John Wall 版本五:偏積極開放,強調後續合作 如您有任何建議或補充,歡迎隨時交流。期盼後續合作順利。 Looking forward to your valuable input and continued collaboration. Best wishes, John Wall

[IIS] 拒絕存取路徑 & 開啟資料夾權限

圖片
今天使用者說發生了錯誤,那麼查了之後有 "拒絕存取路徑" 的關鍵字,也想到先前有上一個新版的程式,可能是沒有權限導致,所以就開啟了資料夾權限,以下紀錄。 一、 錯誤畫面 二、對資料夾右鍵,選擇內容 三、新增權限 四、輸入IIS的應用程式集區 先輸入IIS的應用程式集區,在按下檢查,就會產生對應的使用者物件。 以下給幾個範例,如果剛好一樣就複製吧 1. SYSTEM 2. IIS AppPool\.NET v4.5 2. IIS AppPool\.NET v4.5 Classic 3. IIS AppPool\DefaultAppPool 4. IIS AppPool\{your-app} 五、權限設定。 基本上就跟Admin的一樣,或是看專案需求。 參考資料: https://scotthsucodinglife.blogspot.com/2022/08/iis-iis.html

[SQL] MSSQL 使用 ROW_NUMBER 替代 GroupBy

圖片
如題,之前寫過許多類似情境但未紀錄,所以本次也記錄一下。該需求主要是"找出多個類別中特定條件的資料",聽起來很複雜,實際案例如: <找出每個員工最新的銷售紀錄>,這種情境若使用Group By寫會非常複雜,因為Group By需要聚合函數,所以可以使用ROW_NUMBER 替代 Group By。 不廢話,以下為範例程式碼: -- 建立 Temp Table CREATE TABLE #EmployeeSales ( EmployeeID INT, EmployeeName NVARCHAR(50), SaleDate DATE, SaleAmount DECIMAL(10, 2) ); -- 插入測試數據 INSERT INTO #EmployeeSales (EmployeeID, EmployeeName, SaleDate, SaleAmount) VALUES (1, 'Alice', '2023-05-01', 500.00), (1, 'Alice', '2023-05-05', 800.00), (1, 'Alice', '2023-05-10', 200.00), (2, 'Bob', '2023-05-01', 300.00), (2, 'Bob', '2023-05-03', 700.00), (3, 'Charlie', '2023-05-01', 400.00), (3, 'Charlie', '2023-05-08', 600.00), (3, 'Charlie', '2023-05-10', 900.00); -- 使用 ROW_NUMBER() 實現類似 GROUP BY 效果 SELECT EmployeeID, EmployeeName, SaleDate, SaleAmount FROM ( SELECT EmployeeID, EmployeeName, S...

[C#] .Net Core Mvc 的 Action 找不到及Naming Rule of Async

 如題,.Net Core 遇到Action 找不到的問題,發現是 Async 的命名規則有調整。 可以查看看 MvcOptions.SuppressAsyncSuffixInActionNames Property 有說到,會自動將 Async 關鍵字忽略,提供一下處理方式。 1. 使用Url時移除Async字眼 @Html.ActionLink("送出", "SaveData", "User", new { UserId = item.UserId, UserName = item.UserName }) 2. Controller 加上 [Route("[controller]/{Action}Async")] [HttpPost] [Route("[controller]/SaveDataAsync")] public async Task SaveDataAsync(string UserId, string UserName) { // TODO... return RedirectToAction("Index"); } 3. 調整設定,不忽略"Async" // .NET 6 / .NET 7版本 public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(options => { // 當設為 true 時,MVC 會自動忽略控制器動作方法名稱中的 "Async" 字樣 options.SuppressAsyncSuffixInActionNames = false; }); } // 舊的 services.AddMvc() 寫法 services.AddMvc(options => { options.SuppressAsyncSuffixInActionNames = false; }); 4. 統一將 Async 改為 Asynch...

[C#] 無法載入檔案或組件 或其相依性的其中之一。 找到的組件資訊清單定義與組件參考不符。 (發生例外狀況於 HRESULT: 0x80131040)

圖片
如提,當專案使用 .NET Framework 時,多少會出現這個問題,尤其是多個專案使用同個套件,如果調整版本時,連帶的依賴套件也會變動,就會造成父子專案的套件版本不同,以下紀錄解決方式。 以下附上情境:  System.IO.FileLoadException: 無法載入檔案或組件 'System.Text.Json, Version=8.0.0.4, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' 或其相依性的其中之一。 找到的組件資訊清單定義與組件參考不符。 (發生例外狀況於 HRESULT: 0x80131040) 分析:       1. 系統認為套件要使用 System.Text.Json, Version=8.0.0.4     2. 但專案中使用的套件 不是  System.Text.Json, Version=8.0.0.4 解決方式:      1. 先確認 bin 裡面的套件版本是多少 。(看起來是 7.0.0)                2. 檢查 App.Config 或是 Web.Config 的套件版本是多少。(看起來是 8.0.4)                3. 檢查 .csproj 的套件版本是多少。(看起來是 8.0.4)                  4. 把  App.Config, Web.Config, .csproj 的版本都改成 7.0.0      5. 清除方案 > 重建方案     

[C#] 節流策略 - Debounce & Throttle

圖片
    最近有一個案子類似搶票功能,雖然公司流量跟台鐵相比真的不足為奇,但因同事們撰寫程式都會發生超賣或太慢的狀況,導致主管總覺得這個很複雜。 當然超賣的根本原因跟節流沒有太大的關係,這部分有機會再紀錄。 主要是設計架構上可以透過節流策略,加強系統的承載能力,所以實作該策略了。 Debounce(去抖動) ● 作用:在事件頻繁觸發時,只在最後一次事件觸發後的一段時間內執行。 ● 特點:若在等待時間內再次觸發,計時器重置,直到最後一次觸發後才執行。 ● 應用場景:表單輸入自動保存、搜尋框輸入後延遲查詢、網路請求。 Throttle(節流) ● 作用:在固定的時間間隔內限制事件的觸發次數。 ● 特點:保證在特定時間段內最多執行一次,即使事件頻繁觸發。 ● 應用場景:滾動監聽、按鈕防連點、視窗調整大小事件、網路請求。 Trailing Throttle(結合去抖動和節流) ● 作用:在固定的時間間隔內限制事件的觸發次數,並 確保執行最後一次 事件 。 ● 特點:保證在特定時間段內最多執行一次,即使事件頻繁觸發,且會 執行最後一次事件 。 ● 應用場景: 節流情境下,但需要執行最後一次 事件 。 這邊也附上一個js的應用場景( throttle vs debounce ),比起rxjs的圖,這應該是最好理解的方式了,大家可以觀察一下兩者的區別。 Debounce(去抖動) using System; using System; using System.Collections.Concurrent; using System.Threading; using System.Threading.Tasks; public static class Debouncer { static ConcurrentDictionary _tokens = new ConcurrentDictionary (); public static void Debounce(string uniqueKey, Action action, int millisecondsDelay) { // 如果已經存在 uniqueKey 的 ...

[Testing] 壓力測試 load testing - locust

圖片
    簡單紀錄一個壓力測試工具 - Locust,Locust 是一個開源的壓力測試工具,用於模擬大規模並發用戶請求來測試 Web 應用和 API 的性能。它使用 Python 腳本定義測試行為,支持分佈式測試,並提供簡潔的 Web 界面來監控測試結果,適合進行靈活且可擴展的性能測試。 Locust 特點: 1. 使用簡單:基於 Python 腳本,靈活且易於編寫自定義測試場景。 2. 實時監控:提供友好的 Web UI,實時查看測試結果和性能數據。 3. 可擴展性強:支持分佈式測試,能夠模擬大量並發用戶。 情境: 1 . 目的為搶票。 2 . 組合兩個API測試,一個是取票(book_event),一個是取得當前票數名額資料(search_event)。 3 . 提供一組使用者資料,做為壓力測試資料。 4 . 每次隨機取一個使用者發起請求。 提前補充: 1. Locust有很多進階的應用,目前只記錄最基本的功能。

[SQL] Oracle查無資料 (因 SESSION, NLS, AMERICA...因素)

圖片
    如題,近期公司導入 Oracle,導致程式碼需要調整,卻遇到當前環境查無資料! 但窗口卻說權限有開了,所以紀錄下解決問題的方式。 ● 情境: 1. 窗口提供同義詞(Synonyms) 2. 因公司別不同,窗口也提供一個方法切換公司別,假設為 SET_COMPANYID_CONTEXT ● 解決思路: 1. 先詢問窗口他們使用了哪些NLS_PARAMETERS,通常會變的是 NLS_LANGUAGE,因為中文版更新頻率低,所以常使用美國版。 2. 再來就是更新當前環境的NLS_PARAMETERS,確認看看有無資料。 3. 最後就是在程式中提前設定好NLS_PARAMETERS。 Step1: 查看當前環境的 NLS_PARAMETERS -- 查詢出當前環境的 NLS_PARAMETERS SELECT * FROM V$NLS_PARAMETERS; -- 查詢出可使用的 VLS VALUE SELECT * FROM V$NLS_VALID_VALUES Step2: 當前環境執行語法,確認是否有資料 ALTER SESSION SET NLS_LANGUAGE='AMERICAN' Step3: 程式提前設定  NLS_PARAMETERS 重點是要在每個 connection 連接後,提前設定即可。 //... using (var sessionCommand = connection.CreateCommand()) { // 修改 NLS_LANGUAGE sessionCommand.CommandText = "ALTER SESSION SET NLS_LANGUAGE='AMERICAN'"; sessionCommand.ExecuteNonQuery(); // 修改 NLS_DATE_LANGUAGE (假設比對結果有差異就要加上) sessionCommand.CommandText = "ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN'"; sessionCommand.ExecuteNo...

[SQL] DB Lock

  Sql Server 常常會遇到 Lock 的問題,重點是要查出哪邊卡住,並且看如何處理,以下查詢方式。 SELECT r.session_id, r.status AS [指令狀態], r.command AS [指令類型], r.wait_time/1000.0 AS [等待時間(秒)], s.client_interface_name AS [連線資料庫的驅動程式], s.host_name AS [電腦名稱], s.program_name AS [執行程式名稱], t.text AS [執行的SQL語法], r.blocking_session_id AS [被鎖定卡住的session_id] FROM sys.dm_exec_requests r INNER JOIN sys.dm_exec_sessions s ON r.session_id = s.session_id CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) t WHERE s.is_user_process = 1; 上圖可以看到被 session_id 79 卡住了,但重點是時間非常就,狀態是 KILLED/ROLLBACK,表示已經執行KILL了,還是卡住。這就需要重啟SQL Server了。 若是一般的執行,應該Kill就可以了。 參考資料: https://www.uuu.com.tw/Public/content/article/20/20201207.htm

[Linux] Docker中 COPY 和 -v 的使用場景

  使用 -v 參數來掛載外部路徑到 Docker 容器內是開發階段非常常見的做法。這樣做的好處是,你可以在本地編輯代碼,並立即在 Docker 容器內看到變更,無需每次都重新構建映像。以下是兩種情況的對比: 1. 使用 COPY 指令在構建映像時複製文件 這種方法適合於構建最終的生產環境映像。構建完成後,所有的應用程式文件都被複製到了 Docker 映像中。 Dockerfile 複製程式碼 示例: FROM php: 8.2 -cli WORKDIR / var /www # 會將本地的檔案複製到 WORKDIR /var/www COPY . . RUN php -r "file_exists('.env') || copy('.env.example', '.env');" && \ php artisan key:generate && \ composer install EXPOSE 8000 CMD [ "php" , "artisan" , "serve" , "--host" , "0.0.0.0" , "--port" , "8000" ] 2. 使用 -v 參數在運行容器時掛載本地路徑 這種方法適合於開發階段。你可以在本地編輯代碼,並立即在 Docker 容器內看到變更。 Dockerfile 示例(更簡單): FROM php: 8.2 -cli WORKDIR / var /www RUN php -r "file_exists('.env') || copy('.env.example', '.env');" && \ composer install EXPOSE 8000 CMD [ "php" , "artisan" , "serve" , "--host" , "0.0.0....

[Program] 三分鐘連猴子都能理解的遞迴核心

圖片
  不論您是否有寫過程式,本文目的就是讓任何人都可以在三分鐘理解遞迴的核心。 遞迴是程式中很常使用的到,但對於初學者來說確實有一點門檻,本篇就以[反向重組字串]範例說明。 目標: 反向重組字串,假設我有一個字串為"ABCD",我要反向重組字串為"DCBA"。 這個看似很容易,但是 如果有10000個字呢?  這時候就可用使用程式的 遞迴 來完成了。 反向重組字串,我們從人類的角度看,就是: 『把最後一個字記錄下來,並且把那個字移除,並組合起來』 然後不斷重複這個邏輯對吧,這就是遞迴! 而程式中就會把這個邏輯定義成一個方法 function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 遞迴我認為可以拆解成兩個字,對照本範例如下: *把最後一個字記錄下來,並且把那個字移除 => 「遞」 *資料組合起來 => 「迴」 *要執行「迴」的步驟時,須要觸發判斷條件,也就是終止「遞」的步驟,否則就是無窮迴圈!! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 而把這個過程轉成一個固定邏輯,重複使用該邏輯就是遞迴的核心!!! 遞迴的核心就是 "自己" 呼叫 "自己" ! 也因為自已呼叫自己,會有一層一層往內傳、多層嵌套的概念,就向俄羅斯娃娃一樣~ 那先用一張圖,快速理解 反向重組字串 的過程。 後面用文字說明主邏輯: 1. 第一次呼叫方法,傳入 'ABCD' ,紀錄最後一碼 'D' ,並移除 'D' ,將 'ABC' 往下傳。 2. 第二次呼叫方法,傳入 'ABC' ,紀錄最後一碼 'C' ,並移除 'C' ,將 'AB' 往下傳。 3. 第三次呼叫方法,傳入 'AB' ,紀錄最後一碼 'B' ,並移除 'B' ,將 'A' 往下傳。 4. 第四次呼叫方法,傳入 'A' ,紀錄最後一碼 'A' ,並移除 'A...