看板 mud 關於我們 聯絡資訊
最近有人問,思考了一下做法,以下是偏懶人做法,例如各 mud 大致都有 chinese_number 這個 simul_efun,比方: int n=12345; string sn=chinese_number(n); write(n+" = "+sn); 結果 12345 = 一萬兩千三百四十五 那問題就是如何把 一萬兩千三百四十五 轉回 12345,簡單的做 法是土法煉鋼: int return_n(string sn) { int i=0; while(i++>=0) if(sn==chinese_number(i)) return i; } 但是這樣的問題就是無效的呼叫太多,而且數字越大,迴圈越久 ,這時直覺的想法就是做個簡單的區別,例如假設整數最大數值 是 21 億多: int return_n(string sn) { mixed tmps=({}); int n=0; if(strsrch(sn,"億")) { tmps=explode(sn,"億"); if(sizeof(tmps)<2) tmps+=({"零"}); for(i=1;i<10000;i++) if(tmps[0]==chinese_number(i)) break; n+=i*100000000; sn=tmps[1]; } if(strsrch(sn,"萬")) { tmps=explode(sn,"萬"); if(sizeof(tmps)<2) tmps+=({"零"}); for(i=0;i<10000;i++) if(tmps[0]==chinese_number(i)) break; n+=i*10000; sn=tmps[1]; } for(i=0;i<10000;i++) if(sn==chinese_number(i)) break; n+=i; return i; } 也就是把它拆成看多少個億、然後底下多少個萬、再底下有多少, 去各自做解析,這樣迴圈可以跑少一點。 進一步來說,針對多少個億、多少個萬、..,還可以做以下的解析 int return ranges(string tmp_sn) { if(strsrch(tmp_sn,"千")) return ({1000,10000}); else if(strsrch(tmp_sn,"百")) return ({100,1000}); else return ({0,100}); } 然後上面的 return_n 函數內部份做改寫如下: mixed ranges=({}); if(strsrch(sn,"萬")) { tmps=explode(sn,"萬"); if(sizeof(tmps)<2) tmps+=({"零"}); ranges=return_ranges(tmps[0]); for(i=ranges[0];i<ranges[1];i++) if(tmps[0]==chinese_number(i)) break; n+=i*10000; sn=tmps[1]; } 它的意思是: 如果是一千兩百三十四,那 for(i=1000;i<10000;i++) 就好 如果是一百二十三,那 for(i=100;i<1000;i++) 就好 如果是五十九,那 for(i=0;i<100;i++) 就好 根據以上,還可以進一步改寫 return_ranges 函數: int return ranges(string tmp_sn) { int t; if(t=strsrch(tmp_sn,"千")) { switch(tmp_sn[t-2..t-1]) { case "一": return ({1000,2000}); break; case "二": case "兩": return ({2000,3000}); break; case "三": return ({3000,4000}); break; . . case "九": return ({9000,10000}); break; } } 上面的判斷也可以寫成函數比方 return_units int return_units(string tmp_unit) { switch(tmp_unit) { case "一": return ({1000,2000}); break; case "二": case "兩": return ({2000,3000}); break; // 留意 2 會有二跟兩 case "三": return ({3000,4000}); break; . . case "九": return ({9000,10000}); break; } } 這樣 return_ranges 就可以改寫為 int return ranges(string tmp_sn) { int t; if(t=strsrch(tmp_sn,"千")) return return_units(tmp_sn[t-2,t-1]); else if(t=strsrch(tmp_sn,"百")) return return_units(tmp_sn[t-2,t-1]); // 百以下就不管了 for(i=0;i<100; 迴圈數不多) else return ({0,100}); } 比方 如果是三千兩百二十一,那就 for(i=3000;i<4000;i++) 那可不可以再進一步解析讓迴圈少跑一點呢? 可以,但是,沒必要, 我一慣的想法是: 把解析寫得很簡單 => 程式跑起來loading大 把解析寫得很複雜 => 程式跑起來loading小 那根據均值定理,必定存在一種寫法,可以取得平衡,即程式解析不 用寫得很精確,程式跑起來loading也不會太重就好了。 (上面的程式及函數段,我沒有實際跑過,可能會有 error 要 debug) 以上,一點分享。前提是中文數字的產生均是透過 chinese_number ,例如說如果你要程式解析 "玖壹壹",這是辦不到的,因為通常在 mud 裡頭不會把 int n=911 解成 "玖壹壹",而會解成"九百一十一" Laechan -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.33.66.104 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/mud/M.1636941239.A.C4C.html laechan:轉錄至看板 mud_sanc 11/15 09:54
laechan : 以上的東西其實也可以用在防機程式,即跑出一行中文 11/15 09:56
laechan : 數字,要使用者鍵入它的阿拉伯數字是多少 11/15 09:56
roujuu : 呼叫 siri。^^;;;(認真貌) 11/15 22:35
tsetsethatha: 感謝分享!! 11/16 22:17