2019年4月6日 星期六

自幹發光眼鏡

故事是這樣子的,去年十月跟傳說中的幣圈大佬小新大大弄完 Nixie Tube Clock,從小新大大那邊拿到一團剩餘零件,剛好裡面有一批 1206 的白光 LED,想說丟回收前還是可以利用一下,不如就來做個發光眼鏡好了。

準備材料:不要的眼鏡一副、描圖紙、1206 白光 LED、電線、強力膠、220 Ohm 電阻、供電用的 arduino、焊接工具。

首先要把 1206 發光側貼在眼鏡周邊,我試過一定要用強力膠才能黏得住,保麗龍膠跟雙面膠都無法,焊上電線之後扯 LED 的力道出乎意料的強,光電線本身的彈力就能把 LED 再扯下來,其實就算是強力膠用力扯還是會脫下來,使用上要小心一點。
註:強力膠與保麗龍膠感謝強者我室友贊助。
鏡面的部分要貼上描圖紙,才能把光擋下來做出發光的效果,當然貼上描圖紙之後眼鏡就看不到東西了…;最後是把 LED 上焊上電線,焊上之後就要特別小心別把 LED 扯下來了。
最後接上電源,記得 LED 要串聯 220 Ohm 的限流電阻,這樣發光眼鏡就完成啦。

成品:

來看看效果:
啊發光有點不均勻……不過就算了,真的要均勻就要多一點 LED 才行,至少內側也要一組,接線會變很麻煩,直接買燈條應該會簡單很多啦,連焊接都省了,但燈條就是比較貴一點就是…。
至於醜醜的電線…如果有閒的話是可以拉去後面,但有點懶得弄,總之有效果了,我們可以來玩一些東西,像是:

認真發光:

眼神閃爍(物理)
眼神高頻閃爍(物理)

好啦…其實這個東西只是來亂的,大家可以不用這麼認真XD。

2019年3月19日 星期二

維基百科上繁簡內容的修訂

故事是這樣子的,最近小弟在看 github 上一個 os 的教學,跟 jserv 大大的 mini-arm-os 有點像,都是教你從頭幹一個作業系統出來,只不過這個是幹在 X86 處理器上,某種程度上我覺得在 X86 上寫開機程式根本是各種考古,還要從 real mode 一路開上來(yay
最近剛寫好小弟第一個 X86 kernel ,結果因為在 link kernel 的時候,object 檔案的順序寫錯,害我 de 了一輪搖曳露營 OST的 bug,超白痴。

扯遠了,其實這篇是要講 wiki 的,在寫作業系統的時候不免會去查一些 wiki 資料,然後就發現某些條目充滿了中國風格的用語,當然上面選擇台灣正體也不是看不懂但就是煩,於是把過去註冊密碼忘了的 wiki 帳號找了回來,自己來做個編輯,這裡記錄一下流程,希望大家有看到類似的狀況也可以順手修正一下。
我看到的文章是這篇:X86 呼叫慣例

參考用的資料:wiki 繁簡處理說明

首先先打開上例的 X86 呼叫慣例的頁面,會發現網址的部分,其實是 zh-tw/X86调用约定,這是因為 wiki 的規定是所有的中文頁面都是同樣的內容,再用之後會提到的轉換方式,轉換為中國(zh-cn)、新加坡(zh-sg)及馬來西亞(zh-my)三種簡體中文;台灣(zh-tw)、香港(zh-hk)和澳門(zh-mo)三個繁體中文。
所以在條目上變成先佔先贏,也就是有了「X86调用约定」的頁面的話,就不能新建「X86呼叫約定」的條目,必須只能編輯這個頁面,請見繁簡轉換的條目標題
然後編輯內容也不能隨意將簡體轉成繁體或反向轉換,否則會被視為破壞;另外文中的異體字、日本漢字也都有自己的處理方式,不過這裡我們今天不會提到。

這麼做的好處,就是無論簡體或繁體都會貢獻中文的所有頁面,壞處就是用語、行文等習慣,會需要花費時間轉換,而且我很懷疑能不能轉得好,像是文字轉過去了文法卻沒法用轉換的,對編輯者來說也很麻煩,像我如果要編輯簡體先到先得的頁面,就得要用簡體編輯才行,我個人是覺得壞處是大過好處的…但總之這是現下 wiki 的政策,再怎麼智障也只能先遵循(我其實找不太到這個政策形成的過程,也許有知道的人可以補個脈絡)。

再來就要到所謂地區詞處理了,請見wiki 地區詞處理說明:例如 stack 繁體為堆疊,中國簡體則是堆栈或栈,現下 wiki 的做法就是本文一律先到先得,編輯者是簡體中文就寫簡體中文,讀者選擇台灣正體的時候,再轉換成繁體頁面。
這裡的系統畫成階層圖大概是這樣:

愈下面的地區碼針對性就愈強,指定 zh-mo 就只會在澳門繁體頁面才會轉換,但指定繁體中文就會在下面三個語言都轉換;另外 wiki 有幾個不同階層的轉換:由上而下為全域轉換、全文轉換、公共組轉換、單獨轉換來處理。

  • 全域轉換就是超暴力所有 wiki 範圍內的文字都轉換,誤殺率很高,只有非常針對絕對不會誤殺的詞才能進去,例如台灣正體轉換表的:米芝蓮=>米其林。
  • 全文轉換雷同,只是在一篇文章內通殺。
  • 公共轉換組應該是最實用的,也就是針對資訊科技,定義好一系列的對照表,這些對照表就能套用到跟資訊科技相關的文章中。
  • 單獨轉換就是用來針對固定位置的詞來做轉換

我在看到 X86调用约定的時候,就是因為沒上資訊科技的公共轉換組:IT,以致雖然是繁體頁面內容卻都是中國用語(例如標題轉換成 X86調用約定),修正方式也很簡單,在原始碼的部分加上 NoteTA 的轉換模版就好:
{{noteTA
|T=zh-hans:X86调用约定; zh-hant:X86呼叫慣例;
|G1=IT
}}

其中 T 表示標題的轉換
G1~Gn 則是引用公共轉換組,這裡引用一個 IT 的,至於你說為什麼我知道要引用這個…呃…目前我只知道從類似條目去找,或者從全部的列表裡去找(yay

其實只要加上公共轉換組,看起來就會順眼很多了,自然會有一些詞沒修正到,只能之後手動下去修,像公共轉換組只定義堆栈要轉成堆疊,但原始碼有人只寫栈就轉不過去了。
大概就是這樣,要讓 wiki 用詞跟習慣一樣,還是需要大大們多多動手做點小修改,我個人還是覺得把簡體跟繁體頁面合併滿白痴的,你看我們定義了這麼多的公共轉換組,其實連個 X86呼叫慣例都轉換不好,說到底簡體中文跟繁體中文已經不是文字上的差別,而是連文法上都有差異了吧

2019年2月12日 星期二

關於費式數列的那些事

最近費式數列實在有點紅,讓小弟忍不住也來玩一下。
費式數列給一個初學程式的人都能寫得出來,例如早年我忘了哪位大大在推坑我 python 的時候,就寫了個只要 4 行列出費氏數列的 python 程式,一方面展現 python 在大數運算上的實力,一方面展視了它的簡潔,像是 a , b = a+b, a 這種寫法。
a = b = 1
while b < 1000000000000:
  print(b)
  a, b = a+b, a
當然會寫是一回事,深入進去就沒那麼簡單了,詳細請參考這個網頁
最簡單、最直覺的遞迴寫法,但這其實是會噴射的,每次遞迴都會做重複的計算,於是計算以指數的方式成長,比如說我用 python 的 timeit 去測一個遞迴的費式數列函式,很快執行時間就會爆炸,大概到了 fib(30) 以上就會跑得很吃力了。
如果我們用單純的加法,從 1 開始往上加,其實只要進行 n 次的加法就能得到 fib(n) 了,執行複雜度為 O(n);如果再套用更快的 fast fibonacci,更可以把執行時間拉到 O(lg n) 的程度,只要 fib(94) 就超過 64 bits 的整數的情況下,用 O(lg n) 的演算法其實跟常數時間所差無幾。
不過呢,費式數列還有一個公式解呢,也就是:
$fib(n) = \frac{1}{\sqrt{5}}(\frac{1+\sqrt{5}}{2})^n-\frac{1}{\sqrt{5}}(\frac{1-\sqrt{5}}{2})^n$
為什麼不用這個算式算呢?公式解不是常數時間嗎?

數學上來說:是的,但實際上會遇上一些問題,例如我們看看 64 bits 整數裡面最大的 fib(93) 為例,整數算的解為:
12200160415121876738
如果是 python 寫的公式解呢?
def fib(n):
    return (math.pow((1+math.sqrt(5))/2, n) - math.pow((1-math.sqrt(5))/2, n)) / math.sqrt(5)
print(int(fib(93)))
12200160415121913856
登登,問題大條了,答案不一樣。
何以致此,問題就來到浮點數的不精確問題,這時候就要先來一張經典的漫畫了:
我們在計算完 sqrt(5) 之後,只能用一個近似的值來表達結果,在 python 內預設是以雙精度浮點數在儲存,它跟真正的 sqrt(5) 還是有細微的差距,在隨後的 n 次方、除法上,這個細微的誤差都會被慢慢的放大,最終導致這個巨大的誤差。

幸好我們不是沒有解法的,參考了 C/C++ 版上,傳說中的 Schottky 大大曾經分享如何使用 gmp 或 mpfr 兩個函式庫,算出 e 到小數點下一億位pi 到小數點下一億位,這兩個 gnu 函式庫是所謂的<無限>位數的整數跟<無限>精確度的浮點數,當然他們不是真的無限,只是完全壓榨記憶體來記錄儘可能多的位數以求精確,理論上記憶體撐上去就能把精確度逼上去,只是有沒有那個必要就是,像是把一些無理數算到一億位(欸。
究竟這個函式庫有多麼的強大呢?我們可以來寫個簡單的,例如來算個黃金比例,只要這樣就結束了:
mpfr_t phi;
unsigned long int precision, x=5;
uint64_t digits = DIGITS;

precision = ceill((digits+1)*logl(10)/logl(2));
mpfr_init2(phi, precision);
mpfr_sqrt_ui(phi, x, MPFR_RNDN);
mpfr_add_ui(phi, phi, 1.0, MPFR_RNDN);
mpfr_div_ui(phi, phi, 2.0, MPFR_RNDN);
mpfr_printf("%.10000Rf\n", phi);
mpfr_clear(phi);
唯一要注意的是 mpfr 內部用的 precision 是以 2 進位為底,所以我們在十進位需要的精確度,要先換算為 2 進位的位數,再來就能直接算出 phi 啦,試著算過 50000 位數再對個網路上找的答案,數字是完全一樣的。
這個 library 算得非常快,一百萬位的 phi 也是閃一下就出來了,一億位在我的 64 bit Linux, 2 GHz AMD Ryzen 5 需時 37s,相比 e, pi 這類超越數,phi 只需要 sqrt(5) 真的是非常簡單的了。

扯遠了拉回來,如果我們要用 mpfr 這個函式庫,利用公式解來算 fib(93),要怎麼做呢?
fib(93) 到底有多少位數呢?我們可以用 2^n 作為 F(n) 的上界,最後所需的位數至少就是 ceill(n*log(2)),相對應的我們運算中的浮點數精確度的要求,2^n 這個上界有點可恥粗糙但有用,頂多會浪費點記憶體,最後除出來的小數點後面多幾個零而已,如果能套用更精確的上界當然更好。
mpfr 的函式庫設計精良,呼叫上非常直覺,這段程式碼其實就是寫公式解,應該滿好懂的,程式碼在此。有了這個就可以亂算一堆 fib 了,基本上要算費式數列第一億項 fib(100,000,000) 也是 OK 的(好啦我不保證答案是對的XD,至少 fib(10000) 是對的)。

But,人生最厲害的就是這個 But,公式解真的有比較快嗎?
我個人認為答案是否定的,我們同樣可以用 fast-fibonacci 搭配 gmp 函式庫來計算,因為都是整數的運算可以做到非常快,我的測試程式碼在此

同樣是計算 fib(100,000,000):
formulafib.c: 57.39s user 2.04s system 97% cpu 1:01.09 total
fastfib.c: 4.70s user 0.20s system 75% cpu 6.524 total
O(lg n) 的 fast-fibonacci 遠比<O(1)>的公式解來得快。
問題就在於,到了所謂的大數區域,本來我們假定 O(1) 的加法、乘法都不再是常數時間,而是與數字的長度 k (位元數)有關。而上面我們有提到,基本上可以用 2^n 作為費式數列的上界,也因此費式數列的數字長度 k ~= n,加法、乘法複雜度就會視實作方式上升到 O(n) 跟 O(n^2) 或 O(n lg n) 左右。
在 fast-fibonacci,我們需要做 lg n 次的 iteration,每次三個乘法兩個加減;公式解雖然沒有 iteration,但需要計算兩次次方運算,也等於是 lg n 次的乘法跟加法,然後還有除法,我們運算的又不是整數而是浮點數,這又需要更多的成本,一來一往之間就抵消了公式解直接算出答案的優勢了。

在通常的應用上以及現今電腦的實作,我們還是可以假設整數的加減乘都能在近乎常數時間內結束,這樣我們才能好好討論資料結構與演算法的複雜度,進而把複雜度學好。費氏數列的問題在於,在數字小不用考慮運算複雜度的時候,公式解和 O(lg n) 的 fast-fibonacci 看不出差異,等到 n 終於大到看得出 O(lg n) 跟 O(1) 的差異時,已經要把運算複雜度納入考量了。
理論上我們當然可以假設有個計算模型,無論有多少位的數字,無論浮點數有多少精確度要求,四則運算與次方都能在常數時間內結束,這時公式解就能來到 O(1),但這樣的假設不像停機問題假設的萬能機器,在學術討論上看來不太有意義。
利用 gmp, mpfr 這樣的函式庫,插滿記憶體甚至把硬碟當記憶體來用、把記憶體當 cache 用,浪費幾個星期跟一堆電力,我們可以把無理數算到小數點下一億位、十億位,這是前人們精心為我們建的巨塔,可是數字還是無窮無盡,站在巨塔上反而才看得出我們跟無限有多麼遙遠,誠然人腦可以透過思考一窺數學之奧妙,但不代表我們能超脫數學的嚴格限制浮空而起,妄想記錄無限,我認為是對數學的一種褻瀆。

看了這麼多碎碎念大家想必也累了,總而言之本文透過兩個實作,讓大家體會一下所謂 O(1) 公式解並不一定是 O(1),背後一定有對應的成本;還有就是把費式數列算到一億位真的有點爽,不過我想是沒什麼公司在實務上有在賣 fibonacci 相關的產品啦,除非你想像日本一樣出個寫滿 e, pi 到一百萬位的書讓人當亂數表來用。

2019年1月24日 星期四

閱讀程式碼的心得

許久以前曾經看過這篇,由傳說中在 appier 大殺四方的 PCMan 大神寫的閱讀程式碼教學

最近剛好因為小弟的工作上,也會需要在有一點點規模的程式庫裡面穿梭,雖然都在打混還是累積了一點點心得,在這裡分享一下,當然小弟還是遠不如傳說中的 PCMan 啦,大家從我這裡連過去上面的文章,看完就可以關掉回家了(誒
如果你還是想加減看一下,小弟比較熟的是 C/C++ 系的靜態語言,寫網頁什麼的小弟就不擅長了;然後個人的經驗是有極限的,例如 Linux Kernel 那種規模的 code 我就從來沒有弄懂過QQQQ。

1. 開 code 之前,先把專案編譯,跑起來:


編不起來的 code 就是垃圾,要怎麼知道你改的程式有沒有問題?要怎麼看到你的修改有發生實際效果?編不起來這一切都沒用,所以從網路上載了個 project 下來,第一步一定是先看說明文件把專案編起來或跑起來。
通常網路專案要不是 autotool 就是用 Cmake,個人是覺得 autotool 的機率還是高一點點,但通常都是下個 autoconf 再接 configure 就能生出 Makefile 了。

2. 看 code 是最後一步,先從高層次理解程式在做什麼:


這是工作一陣子之後的心得,原始碼最底層是一個很細緻層次的東西,例如模擬一個 x,y 的座標值,然後往上一層一層建構線、面、一群面的組合、一群組合的參考/一群組合的陣列參考等等,上層會用高層次在操作,把下面的實作都隱藏起來。
理解高層次的程式在幹嘛,遠比從低視角去理解實作重要(雖然 low angle 拍出來的照片比較香(炸)),沒理解想法跟目的之前,直接看程式碼是沒有意義的,看到函式做一個 loop,可是為什麼要 loop,在 loop 什麼?沒理解想法,連看著處理中的資料無法分辨對錯的時候,就只是看一堆無意義的資料飛過去而已。
比如說最近跟著強者我同學 JJL 大大在看 verilator 這個 project,這個 project 會把 verilog 吃進來,模擬的 C++ 送出去,verilator 發大財,直接進到 src 資料夾會看到滿滿的 V3xxxx 的檔案,但只要緊抓上面的概念,其實大部分都是 AST 的檔案,verilog 會先被 parse 成 AST,由程式對 AST 進行一些處理變形,再把成果寫出去;所以說至少會有 AST node 跟走訪 AST 的程式,從這點抓下去八九不離十了。
理解高層次的程式比較困難,一般函式至少會有註解,可以註記這個函式的功能,但高層次想法是一個比較難表述的東西,通常也不會訴諸文字,只會記在開發者的腦袋裡面,如果能有一個人帶領的話通常效率會快很多。

3. 調校好工具:


工具上的投資非常值得,好的工具能省下極大的時間,要不要用 IDE 個人沒什麼信仰,一般我都是用 vim,這部分請參考幾篇拙作:用 Vundle 安裝 vim 插件,還有用 ctags 幫助跳轉,Ctags 的程式碼跳轉是一定要的,效率直接天上飛。
終端機也是一個值得好好投資的工具,我一般工作都會開 5 個終端機的分頁,前三個用來編輯 code,第四個用來編譯(因為 C 專案通常程式碼跟編譯的 top 不會是同一個目錄),第五個用來執行程式(對因為通常程式碼、編譯跟執行檔不會是同一個目錄),用 Alt+12345 可以很快速的在分頁間切換,到 Alt+6 我覺得就太遠了。
至於多螢幕,我覺得有幫助但有限,最大的用處是在撰寫投影片跟筆記的時候,可以把 powerpoint 跟 word 拉到另一個螢幕去,跟 code 來回對照會快很多,但單純閱讀程式碼的時候是用不上的。
另外一些 shell 相關的部分,請參考拙作<那些在工作上看到的各種東西>的工具部分:

4. 邊看邊做點筆記:


說真的大型專案有些都會到很噁心的地步,還會有一些積非成是的地方,命名不佳的地方,可能當初寫好、修改,改到後來就沒人敢改了。
最近遇到還有印象的是這樣:我們會依序分解,一條線 x、x 的其中一個端點 S、S 的兩個端點 X1, X2,分別傳進去給函式 A, B, C 做處理,但函式 A 裡面 S 在 x 的 index 跟函式 C 裡面 X1 的 index,變數竟然都用 index,然後在函式 A, B 裡面,都用 i 變數來 pass 給下層的函式,變成裡面的 index。
搞到後來到底 index, i 在哪裡代表什麼都一團糟,這裡就很適合簡單畫個表格記錄一下;要隨手 refactor 一下也是可以,但在大型又缺乏維護的專案下,refactor 有可能會花很多時間,這部分就要自己取捨了。

5. 順手做點修改?


參照上一點,做點變數修改、加些註解,幫助自己理解程式碼是 OK 的;但要記得,一定要沉住氣,不要去改一些枝微末節的東西。
例如有些專案會是悲劇性的空白 tab 混用的狀態,這就不要改了,第一個這個會引發比無限之戰更慘烈的信仰之戰,第二是這種大範圍的修改很浪費時間;第三這種修改很難進入主線,設定一下 tab 的寬度讓程式碼排版回到容易看的狀態就好。
如果有一些區塊很難讀懂,可以用 vim 的 = 在區塊內做重新排版(雖然我覺得這個功能爛掉的機會滿大的)
再來是 syntax sugar,例如自從 C++11 的 range-based loop 出來之後,看到舊式的 iterator based loop 都會覺得癢癢的,是不是該順手改過去?個人認為是不需要。
syntax sugar 的本意就是:更易讀或表達更簡單的文法,本質上無關乎背後的實作,所以你動了手一方面對程式其實沒半點影響,通常 iterator-based 的 loop 也不會影響閱讀跟理解,還不如把精力省下來看懂程式想做什麼。

要知道大型或是正式的 project ,review 機制完善之後所有的修改都會需要審核,沒事沒頭沒尾的送一個修了一堆東西的 Pull Request 被接受的機率都很低,另外 syntax sugar 等級的 refactor 其實根本不影響程式效能,真正架構上、想法上的 refactor 才會,記住程式開發最浪費時間的東西就是程式人的腦袋,不要浪費時間在低層次的修改上面,專注在高層次的程式流程上。
大型的專案通常都橫跨十幾年,會有老舊語法跟 legacy code 是很正常的事情,我現在做的專案裡面還有 K&R C 的 parameter style 勒,就像下面這種:
int foo(bar, qux)
int bar,
stNode qux { … }
反正編譯器還支援的狀況下留著也沒差,我敢打賭這種 code 還會在公司的程式裡留 10 年以上;記得 syntax sugar 只能加在熱咖啡裡,咖啡冷了就不要浪費精力加糖,想辦法換杯新咖啡比較重要。

6. 從 main 下手:


不知道從哪裡開始,我個人的經驗是從 main 下去最快。
main 通常(通常就是有例外啦)會保留最多高層次的程式邏輯跟想法,如果在 main 裡面看到低層次的操作那也是滿抖的。
以 verilator 為例,main 位於 verilator.cpp,整個結構其實很單純:剖析傳進來的參數,讀檔,process,將結果 dump 出來。process 裡面就是對 verilog AST 進行處理的各個 visitor 呼叫,trace 一下就能清楚整個程式的大體流程了。
當然這個規則無法一體適用就是了,具體還是要看各 project 的架構,我也看過最上層是一套虛擬機的專案,實作功能都拆分為給這個虛擬機執行的函式,這時候進入點就變成各函式而不是 main 了。

以上大概就是幾個工作到現在累積的看原始碼心得,小弟班門弄斧,希望各位看倌大大有什麼意見都能多多回饋給小弟。

2019年1月12日 星期六

省錢是好事嗎

故事是這樣子的,最近有一位很紅的藝人 BBB 拍了高雄市拍了一部 MV,他的宣傳詞是這樣寫的:「BBB 自掏腰包為高雄拍攝的MV『來去高雄』,懇求大家幫助負債累累的高雄市政府不用花任何一毛宣傳費,就可以讓大家湧入高雄拚觀光!達到宣傳高雄的最大效果,請大家努力、用力的轉發分享MV,靠全民的力量達到最大成效!」
剛好最近,政府宣佈因為上半年的稅收有盈餘,同樣也引發一番爭辯,畢竟現在中華台北還有這麼多債務,稅收有多是不是應該先還債?對照組正好是台北市市長,在第一任任期中主打政績即是償還市府負債。

這一連串看完突然有一點感想,跟之前看書的心得結合一下來寫篇文章。

當然我本文無意支持或反對現下政府將稅金盈餘退,或者 BBB 的影片是好是壞有效無效,純粹就貼文背後的精神來評論。
我覺得這篇貼文剛好非常傳神的傳達了兩個概念:
1. 負債累累的高雄市政府需要幫助。
2. 不花政府一毛錢就是讚,大家要多鼓勵。
相對應到退稅議題上面,就是:
1. 負債累累的政府不應該再退稅。
2. 政府不該亂花錢,應該努力減少負債。
說起來有點華國人老一輩刻苦經營儲蓄的精神。

我們常被教導/認為的省錢就是好,負債就是壞,真的嗎?

假設我們地方政府一年歲入是 400 億元,而台北捷運第一期的工程就花了 4000 億,很明顯的如果政府是無法一口氣開工所有的捷運,而必須分年編列預算分年開工;相對的政府可以借債,一口氣先借 4000 億元把捷運蓋完,然後分年的慢慢還債。雖然後者利率會造成多一些成本,可是早點同時開工的話,可以在土地還便宜的時及早徵收,儘早擺脫交通黑暗期,減少道路車禍傷亡,這些都是獲利。
用個更簡單的例子,為何長輩當年都會貸款買房呢?負債不是不好嗎?更別提那個時候借錢利率高得嚇人呢。但借錢買房卻有它的道理在,可以更早享用住房,在房子便宜的時候先買,負債+房子也可能比滿手現金來得保值。
或者再簡單一點,假設今天持有台GG的股票,每年有 2% 的收益,而銀行的利率是 1%,請在「沒有負債沒有股票」跟「欠銀行 100 萬但有等值的台GG股票」兩者間做選擇,前者沒有負債,但以賺錢來看後者才是好的。

上面幾個例子,都在說明省錢是好負債是壞的概念,其實不一定正確,重點要看錢灑出去會換到什麼資產回來,然後評估那個資產合不合理。
我第一次意識到這個觀念,在之前閱讀<21世紀資本論>時裡面的一小段:「殖民時期英法兩國持有的國外資產和帶來的收益,足以使他們承受貿易赤字同時仍有收益……汲汲營營堅守貿易順差本身沒有任何意義,持有資本的根本目的就是能在不工作的狀況下,繼續消費、累積資本」。
同樣的,所有的資產應該要攤開來看,堅守黑字不是絕對,有錢無債只意味著持有「錢」這個資產,而放棄其他可能更高報酬,拿債滾錢的選擇;畢竟長期來看,隨著通膨錢這個資產可能是最沒價值的(你也可以說錢最不值錢XD),所謂保值,就是在比哪個資產價值流失得比錢還慢;政府可以把錢換成火車、航廈、或者乾脆一點換成未來的小孩也可能更賺,至少他們有機會在未來滾出更多小孩。

當然:省錢是好、負債是錯這是個很鐵的概念,直覺上來說很像真的,強者我同學台大財金系畢業一樣逃不過這觀念的束縛(雖然我私心認為他不是不懂,只是戴著有色眼鏡所以反對啦)。

另外一句:省錢是好的嗎?
同樣不盡然。
比如說,如果省錢很重要,為什麼我每天不走路回家呢?因為我搭公車 15 元車程大概 40 分鐘;走路 0 元大概 2-3 小時,搭公車多出來的時間,我可以多寫幾行程式多看一些書,都能比省下的公車錢更有生產力,在這裡,省錢意味著失去時間這項隱形的成本。
花錢可以換到一些隱形的東西,像是請老師是換他的經驗,買珍奶是換舌尖的快樂,或者那個讓人津津樂道的笑話:一個美國工程師拿一半的薪水請三個印度工程師,把工作都包給他們做,自己上班就可以爽爽過,買工程師是換自己的時間。
就像非常早非常早,當我剛被 Free Software 傳教的時候,都會有一段時間覺得為什麼不要整個社會、政府機關改用 Libre Office 就好了?作業系統全部換 Linux 啊,不是超省錢?碰久一點之後就會發現,要對應世界上這麼多、每個都不同規格的硬體,不像 Mac 筆電因為規格全是硬性規定,Windows 雖然沒事出點包然後使用上被大家幹到翻,在穩定、方便、統一規格上仍然把其他 Mac/Linux 壓在地上打,如果加上 Office 系列產品那又更不得了。
Window 可能要錢,但它有 Microsoft 在背後支持,有 bug 會幫你修,全系列的相容性他們會注意,花錢買得到服務;Linux 是免費的,但它沒有客戶支援,沒有相容性支援,整個體驗加上去可能是負的。
所以才有那句諺語:免費的最貴,不收錢表示它有缺點讓它不夠格收錢,那你看得透那個缺點嗎?花不花錢不是重點,重點是花了錢會換到什麼?權衡利弊,省不是一切。

事實上若綜觀國際商場的現況,諸如共享單車、網購平台、叫車服務等,這幾年都出現透過灑大錢補助來吸引使用者,負債買下市佔率,及早建立規模優勢排除競爭者的手法(當然排除之後活不活得下去是另一回事),這跟做好自己產品吸引消費者上門的手法大相競庭。
HTC 不就是一個血淋淋的例子,作為最早推出智慧型手機的廠商,後來卻慢慢在行銷、通路的資源戰上被對手壓了過去?
堅守省錢少舉債思維的中華台北,宛若二戰時日本拿全民精英射手對付美軍機槍的手法,賺到省下來的小利卻不一定擋不過人家用資源硬推出來的優勢,平常都稱讚中國狼性中國小確幸,來到行銷廣告的時候,眼下就來個標準的範例了,果然還是老話一句:一隻手指指著別人的時候,四隻手指指著自己。
啊不過話說回來我打了這麼多,個人資產配置還是都以現金為主,果然是:一隻手指指著別人的時候,四隻手指指著自己,啊哈哈哈…嗚嗚(誒。

落落長說了一堆不相干的東西,我想可以整理兩個 take-away:
  • 負債不是壞事,重點是要看負債換來什麼;錢只是資產的一個表現,要看整體資產是否有所增長,或者有機會成長。
  • 省錢不是好事,重點是花錢能換來什麼?能不能換到時間、方便、穩定、機會?省錢必有成本,你有沒有意識到呢?
Related Posts Plugin for WordPress, Blogger...