星期三, 6月 18, 2014

國二作文簿 (part 3)

哈哈哈我在寫什麼啦 XD

我喜歡

涼風送爽的季節,百花盛開、鳥語花香、大地一片翠綠。啊!我愛春的原野;烈日炎炎的季節,蟲鳴鳥叫、繁星點點、夕陽一輪火紅。啊!我愛夏的烈日;風高企爽的季節,涼風陣陣、馨香四溢、蝴蝶翩翩飛舞。啊!我愛秋的涼風;冰天凍地的季節,百獸休憩、霜臨大地、世界一片靜寂。(只有「百獸」的打呼聲而已)啊!我愛冬的熱鬧靜寂

看!那清晨的霜露結在草地;那傍晚的天空一片紫紅;那午的烈日竟情揮灑,那入夜的星空光彩奪目。我只要他們的萬分之一;清晨的純潔、傍晚的美貌、午的瀟灑和入夜的紛......(好像在看古早的文藝愛情片)確實

春,醒了,又睡了;夏,醒了,又睡了;秋,醒了,又睡了;冬,醒了,又睡了;早晨,醒了,又睡了;午候,醒了,又睡了;傍晚,醒了,又睡了;夜,醒了,又睡了。可是人,永遠都醒著,也永遠都睡著。醒在夢裡,睡在現實,醉在今宵,活在黎明。

這兩句,正好就是你的寫照!
要老師怎麼批呢?
一、二段真是太棒了
第三段真是太混了


繽繽繽繽繽繽繽繽繽繽繽繽繽繽繽繽繽繽繽

第三段之所以這樣寫,是因為字數夠了......

第一段被劃掉的熱鬧,我的確是故意寫「熱鬧」的。老師大概沒有理解我的修辭手法......

「午候」的「候」,我的確是要寫「候」而不是「後」,所以刻意不訂正。

上標部分是寫在格子旁邊導師批改的留白部分。

理工人不是不能寫矯情油膩的文章,只是不屑寫

星期二, 6月 17, 2014

國二作文簿 (part 2)

翻到國中時的作文簿......(紅字部分為導師批改)

花與樹(新詩創作)

花;
一朵花;
一朵美麗的花;
一朵美麗的小花,
象徵美麗,也象徵脆弱(希望)

樹;
一棵樹;
一朵高大的樹;
一朵高大的大樹,
象徵平凡,也象徵壯碩。

花與樹;
一朵美麗的花語高大的樹。
一朵美麗的小花和高大的大樹。
象徵和諧,更象徵著生生不息。

相同的意境,就不必重複的敘述。
詩,就是貴在言簡而意深,而你的冗句太多

沒法度,要湊篇幅啊!(本句為發還後補上...)

第一段的脆弱是要跟壯碩呼應,導師大概沒看到第二段就批改了。我現在看過,還是覺得放脆弱更恰當。

我一直都是個非常討厭寫字的人。

星期六, 1月 18, 2014

程式設計師 vs. 新聞記者

Android 的 PopupMenu 不支援顯示 icon。可是很多時候你會想放個 icon 給他... 那怎麼辦呢?

深挖 PopupMenu 的程式碼以後,發現他實際是透過 MenuPopupHelper 這個 class 來顯示實際的 PopupWindow,而該 class 有個 setForceShowIcon() 函式,可以用來強制顯示 icon。

可是... 這個 mPopup 在 PopupMenu 裡是 private field 啊... client code access 不到它... 怎麼辦咧?

在這裡有兩個選擇...

  1. 搞肛的辦法...:把 PopupMenu.java 跟所有用到的 internal class 實作複製一份過來,多新增一個 setForceShowIcon() 方法。
  2. 偷吃步:透過 Java 的 Reflection 機制來偷偷存取該 private field。

當然,我不會在這裡講搞肛的辦法,因為我是怠惰的程式設計師,能偷吃步一定要偷吃步的(怠惰的程式設計師施工原則:自己要維護的程式碼越少越好)。

所以,本來這樣的東西:

PopupMenu menu = ...;
...
menu.mPopup.setForceShowIcon(true);

就變成了...:

public static void hackPopupMenuToShowIcon(PopupMenu popup, boolean showIcon)
{
    try
    {
        // 從所有 field 中找出名稱為 mPopup 的 field。
        Field[] fields = popup.getClass().getDeclaredFields();
        for (Field field : fields)
        {
            if ("mPopup".equals(field.getName()))
            {
                // 設定存取權(本來是 private field 不能存取)
                field.setAccessible(true);
                // 取得 popup 這個 instance 的 mPopup
                Object menuPopupHelper = field.get(popup);
                // 取得 mPopup 的 class
                Class classPopupHelper = Class.forName(menuPopupHelper.getClass().getName());
                // 取得 mPopup 的 class 的 setForceShowIcon() 這個 method
                Method setForceIcons = classPopupHelper.getMethod("setForceShowIcon", boolean.class);
                // invoke 該 method...
                setForceIcons.invoke(menuPopupHelper, showIcon);
                break;
            }
        }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

// 使用時變成
PopupMenu menu = ...;
...
hackPopupMenuToShowIcon(menu, true);

感覺就像台灣的新聞記者......

  • 馬總統正在公園慢跑。

硬要寫成

  • 馬總統英九先生目前正在一個被稱作公園的地方執行一個慢跑的動作。

星期四, 1月 09, 2014

RenderScript with AndroidStudio

=== 中文版 ===

我只是想 log 一些用 Android Studio 寫 RenderScript 的 gotcha...

  1. 如果你把 <script-name>.rs 放在跟 .java 同一個目錄,grandle 是不會幫你編的... 你得在跟 src、res 同一層開一個新的資料夾叫「rs」,然後把你的 <script-name>.rs 丟進裡面。
  2. 如果你在執行的時候,出現「Invalid RS info file /data/data/<package>/cache/<package>/<script-name>.o.info! (No such file or directory)」,表示你使用的 build-tool 高過執行環境的 API Level。請改用更低的 build-tool...

    具體作法,是去 build.grandle 裡面,把 buildToolsVersion 改低,例如改成 17...(記得要先去 SDK Manager 裡面裝上更低版本的 build tool。)

=== English Version ===

I just want to log some RenderScript gotcha's while developing with Android Studio.

  1. If you just dropped your <script-name>.rs within the same directory with your .java file, grandle won't compile it for you... You've got to make a new directory aloneside src and res, named "rs", and throw your <script-name>.rs over there.
  2. If you encounter "Invalid RS info file /data/data/<package>/cache/<package>/<script-name>.o.info! (No such file or directory)", that means your build-tool is too new to the environment API level. Switch to a lower version build-tool would make it run.

    In practice, edit build.grandle, switch to a lower "buildToolsVersion", for example 17... (don't forget to install a lower version build-tool with SDK Manager first.)

星期一, 1月 06, 2014

這不是姬兮兮

武漢女大生用數學符號作三行情詩 男友也驚呆

大陸中心/綜合報導

武漢長江工商學院大一女生吳華傑日前用數學符號「-∞」、「+∞」和幾個簡單的英文單詞向男友表達愛意,被同學們稱讚「高端、大氣、上檔次」,並獲得該校舉辦的「三行情詩」徵文比賽一等獎。

《楚天金報》報導,吳華傑是該校經濟與商務外語學院學生,頗喜歡研究、創作五言絕句和七言律詩等古詩詞;在一次上數學課時,她突然想到可以結合數學演算法,為男友寫一首情詩,就開始她的創作之旅:「INPUT (-∞,+∞),IF(-∞THEN+∞],ELSE+∞)。」

吳華傑說,「INPUT是數學語言中輸入的意思,-∞和+∞分別指負無窮和正無窮。第一行詩是指愛情開始時,雙方都在付出。IF是條件陳述式如果的意思,THEN是然後的意思,第二行詩指如果有一方背叛,負無窮付出,另一方就『]』(閉區間符號,特指停止)正無窮的付出。ELSE是否則的意思,第三行詩指彼此如果沒有背叛,就會為對方付出正無窮的愛。這首詩是想告訴男友,你若不離不棄,我定生死相依。」

「這首情詩把數學語言與文學相結合,表達雙方不離不棄的陪伴,牽著彼此的手走到生命的盡頭之意。高端大氣上檔次,一般人真寫不來!」該校清水石文學社代表許黎稱讚道。

吳華傑說,她和男友在讀高中時相識,因當時怕耽誤學業,她一直沒有接受男友的示愛,直至上大學後,兩人才確立戀愛關係。目前,她的男友正在創業,當看到這首情詩時,男友也驚呆了。
  1. 這可能不能算是數學、甚至不能算是程式碼,恐怕只能算是 psuedo-code...
  2. 括號沒對齊...

這讓我想起 PerlYuYanWikipedia 頁面居然被移除了 = =)... 所以寫了一段:

#!/usr/bin/perl
use Lingua::Sinica::PerlYuYan;

#用籌兮 用嚴兮 截起吾純心
#賦小入大合 兮註在君意
#印道我心哉 點起起純心
#等零倘壹合 歟道有情哉
#然曰無情矣 合兮井底空

翻譯...

#!/usr/bin/perl
use Lingua::Sinica::PerlYuYan;

use integer; use strict; chomp (my integer $D
= <stdin>); #在君意
print "我心" . (($D
== 0 xor 1) ? "有情"
: '無情'); #井底空

可是這首詩念一念,除了有點情色部分,好像被甩的話就要抓對方去跳井。

要算計、要嚴格,取一顆純淨的心。
把小的東西放進大的裡面(!?),兩個人情投意合。
在我心上相印,點綴純潔的心。
將 0 與 1 合在一起(!?),是有情還是無情?一起跳進空的井底。

我好無聊 XD

星期三, 6月 06, 2012

遺失

我改用 Chromium 很久了,大概是 Firefox 3 那時候吧!那時並沒有把即時書籤一起加入 Chrome,因為 Chrome 一直到現在都沒有好用的即時書籤 = =

最近因為要逛 Gnome Shell Extensions,把 Firefox(哇!都 13 了!)開起來,就想說看看以前朋友的 blog 還在不在。

我之前總共訂閱了 16 個朋友的 Blog、現在 8 個載入失敗、6 個超過三年以上沒新文章,只有兩個還繼續在寫。

可能大家都改玩 Facebook / Twitter / Plurk 了吧...

... 持之以恆真的很困難 XD
(我自己有時候也會空個一兩年才寫一篇文章 XD)

星期四, 3月 08, 2012

_id、_ID 傻傻分不清楚

最近在寫 Android 的 Database 程式的時候,發現點擊 ExpandableListView 的第一層要讓他展開的時候,總是會出現以下的 IllegalStateException:

E/AndroidRuntime(12706): FATAL EXCEPTION: main E/AndroidRuntime(12706): java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. E/AndroidRuntime(12706): at android.database.CursorWindow.nativeGetLong(Native Method) E/AndroidRuntime(12706): at android.database.CursorWindow.getLong(CursorWindow.java:515) E/AndroidRuntime(12706): at android.database.AbstractWindowedCursor.getLong(AbstractWindowedCursor.java:75) E/AndroidRuntime(12706): at android.database.CursorWrapper.getLong(CursorWrapper.java:106) E/AndroidRuntime(12706): at android.widget.CursorTreeAdapter$MyCursorHelper.getId(CursorTreeAdapter.java:436) E/AndroidRuntime(12706): at android.widget.CursorTreeAdapter.getGroupId(CursorTreeAdapter.java:191) E/AndroidRuntime(12706): at android.widget.ExpandableListConnector.getItemId(ExpandableListConnector.java:421) E/AndroidRuntime(12706): at android.widget.AdapterView.getItemIdAtPosition(AdapterView.java:756) E/AndroidRuntime(12706): at android.widget.AdapterView.setSelectedPositionInt(AdapterView.java:1128) E/AndroidRuntime(12706): at android.widget.AbsListView.onTouchEvent(AbsListView.java:3147) E/AndroidRuntime(12706): at android.view.View.dispatchTouchEvent(View.java:5541) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1951) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1712) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1957) E/AndroidRuntime(12706): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1726) E/AndroidRuntime(12706): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1912) E/AndroidRuntime(12706): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1371) E/AndroidRuntime(12706): at android.app.Activity.dispatchTouchEvent(Activity.java:2364) E/AndroidRuntime(12706): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1860) E/AndroidRuntime(12706): at android.view.View.dispatchPointerEvent(View.java:5721) E/AndroidRuntime(12706): at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:2890) E/AndroidRuntime(12706): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2466) E/AndroidRuntime(12706): at android.view.ViewRootImpl.processInputEvents(ViewRootImpl.java:845) E/AndroidRuntime(12706): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2475) E/AndroidRuntime(12706): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime(12706): at android.os.Looper.loop(Looper.java:137) E/AndroidRuntime(12706): at android.app.ActivityThread.main(ActivityThread.java:4424) E/AndroidRuntime(12706): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime(12706): at java.lang.reflect.Method.invoke(Method.java:511) E/AndroidRuntime(12706): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) E/AndroidRuntime(12706): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) E/AndroidRuntime(12706): at dalvik.system.NativeStart.main(Native Method)

他唯一比較算是「錯誤訊息」的是「Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.」這個,是表示說程式試圖存取某個 column,可是 query 中沒有這個欄位,所以會回傳 -1。於是乎,程式就這麼爆炸了。

可是... 他只告訴我「col -1」,沒告訴我他到底想查哪個欄位啊... = = 所以只好去追程式碼,發現主要是這個東西「android.widget.CursorTreeAdapter.getGroupId()」會試著抓「_id」這欄位。

SQLite 在 create table 的時候,會自動幫你建立叫做「_id」的欄位作為索引。但是如果你的 create table statement 中有包含某個 integer 型態的 primary key,他就會改用這個欄位來索引(就是不會再多建一個「_id』)了。

Android 的 Cursor 會拿這個欄位作為內部索引,會試圖存取它。當找不到這個欄位的時候,就會丟出 IllegalStateException。

可是呢,我很犯賤的在 create table 的時候用了 _ID 作為 primary key,於是即使 query 是「SELECT `_id` FROM `table_name`;」,他回傳的資料中還是會以 _ID 作為欄位名稱...

結論就是... create table 的時候得用「_id」,用「_Id」、「_iD」、「_ID」統統不行... XD~

星期三, 6月 08, 2011

核能發電,該還是不該?

今天看到的新聞:

小英:再執政 十三年後終止核能發電

中國時報【朱真楷/台北報導】

提出「二○二五非核家園計畫」的民進黨主席蔡英文,昨日上午抵達德國考察綠能產業。她表示,德國政府已宣布二○二二年前關閉所有核電廠的政策,證明要達成非核目標的關鍵,在於決策者的決心,所以只要民進黨取得政權,就有信心用十三年的時間終止核能發電。

蔡英文在柏林時間六日上午抵達德國後,在執政黨基民黨國會議員費雪陪同下參訪柏林車站等相關綠能建設。

不要核能發電可以,可是要有替代的發電方案。

我國(中華民國)電能來源中,核能佔了 19.3% 左右(資料來源:台灣電力公司 - 年產銷快訊)。所以說,如果沒有核能發電,這些電勢必要以其他方式來產生。

如果平攤到其他種種發電方法中,意味火力發電(國營 53.4% + 民營 18.7% = 72%)必須增加 19.3% * 72% = 13.9%。

再看到總用電量 1933.1 億度,也就是說火力發電必須增加 1933.1 * 13.9% = 268.7 億度。

如果這些發電改用:

  • 燃煤:產生 268.7 億 kw/h * 1.020 kg/(kw/h) = 274.074 億 kg 的二氧化碳
  • 燃油:產生 268.7 億 kw/h * 0.758 kg/(kw/h) = 203.675 億 kg 的二氧化碳
  • 天然氣:產生 268.7 億 kw/h * 0.515 kg/(kw/h) = 138.38 億 kg 的二氧化碳
  • 核能(原本):產生 268.7 億 kw/h * 0.0661 kg/(kw/h) = 17.761 億 kg 的二氧化碳
p.s. 我忘記在哪裡看到這些數據,請知道的人幫我補... >_<

然後又會跑到令一個惡性循環:二氧化碳升高 = 溫度升高、溫度升高 = 冷氣用量增加、冷氣用量增加 = 用電量增加、用電量增加 = 發電量增加、發電量增加 = 二氧化碳升高...

====== 分隔線 === 分隔線 === 分隔線 ======

話又說回來,如果那些反核的從電廠關掉開始就完全不要用電(除了搬去山裡與世隔絕以外,還有別的辦法嗎?),那就關吧!

星期一, 5月 30, 2011

小叮噹風扇 vs. 數位電視訊號

記者知識不足,才會把這件事當成很嚴重的事情:http://tw.news.yahoo.com/article/url/d/a/110529/8/2se1p.html。懂原理的就會知道,這只是沒什麼大不了的數位信號干擾。

台灣使用的數位電視訊號是 1080p/1080i 的 DVB-T,DVB-T 會將數位訊號用 OFDM(正交分頻多工)打散分佈至 4kHz 或 1kHz 的訊號中。

也就是說,當你有個外部頻率為 4k 或 1k 的因數的訊源時(例如 2Hz、4Hz、5Hz、8Hz、10Hz、20Hz、25Hz、40Hz、50Hz、100Hz、125Hz、200Hz、250Hz、500Hz、800Hz、1000Hz、2000Hz、4000Hz...),就有可能會干擾到數位電視訊號。而超商的小叮噹風扇很有可能剛好就是這個轉速(例如剛好是 1000rpm),所以會產生這些頻率的雜訊干擾數位電視訊號。

而影像資料壓縮通常是以 Block 為單位,所以他解壓縮的時候會有某些 block 解壓失敗,導致下一個 block 被提前或延後。反應到影像上就是部份畫面看起來像在左右抖動。

而吹風機為了吹出足夠大的風量,轉速通常都很高,可以到 10000 ~ 20000 rpm,不容易干擾 1kHz 或 4kHz 的數位訊號。如果你拿轉速相當於前述 Hz 的風扇靠近數位電視訊號接收器,應該也會出現類似的干擾。

星期日, 3月 27, 2011

給一個日期,怎樣知道那天星期幾?

嗯... 這真是個神奇的函式 XD~

int dayofweek(int y, int m, int d)  /* 0 = Sunday */
{
  static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
  y -= m < 3;
  return (y + y/4 - y/100 + y/400 + t[m-1] + d) % 7;
}

-- by Tomohiko Sakamoto.

星期五, 3月 25, 2011

Firefox 4.0 初步使用心得

做了一些 benchmark。我的機器:

  • Intel Core-i7 720QM:performance cpufreq governor
  • Transcend JM1333KSN-4G x 2:在測試時還剩下約 1GB 空間(扣掉 Buffer 則剩 3.5GB)
  • Linux 2.6.38:有開 per-session auto-group(CONFIG_SCHED_AUTOGROUP=y)

參賽的瀏覽器有:

  • Chromium 11.0.696.16:
    Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.16 Safari/534.24
  • Firefox 4.0:
    Mozilla/5.0 (X11; Linux x86_64; rv:2.0) Gecko/20110323 Firefox/4.0
  • Opera 11.10 beta:
    Opera/9.80 (X11; Linux x86_64; U; zh-tw) Presto/2.8.119 Version/11.10

測試 0:

  • Acid3
    • Chromium:100/100
    • Firefox:97/100
    • Opera:100/100
  • 冷啟動速度:
    • Chromium:4.16s(8.33 次)
    • Firefox:1.5s(3 次)
    • Opera:5.16s(10.33 次)

冷啟動速度是執行「sync ; echo 3 > /proc/sys/vm/drop_caches」以後啟動瀏覽器到視窗出現,游標閃爍的次數(每次 0.5s)。測了三次,精度不是很準確... 看看就好!

測試 1 - CPU 0%(幾乎沒有其他負載):

測試 2 - CPU 100%(make kernel, -j16):

其中「大頁面測試」一項,是先重整三次(確認檔案讀進了 filesystem buffer),然後再重整三次的成績平均。Chromium 快的很神奇 @@

為什麼會有在 CPU 100% 下的測試呢?因為我使用 Gentoo Linux,常常會編譯東西。可是在編譯的同時,也會一邊上網、看信... 等等。所以在 CPU 負載高的情況下使用瀏覽器是很常有的事情。

跑 Sunspider 的時候,Chromium 會更新每個跑完的測試結果,可是 Firefox 完全不會顯示東西(這算是偷吃步嗎?),Opera 會顯示,但是中間的藍色方框內會閃爍。

對我來說,瀏覽器的速度(網頁顯示速度、分頁切換速度、UI 反應速度)很重要。我無法忍受切換分頁或點個書籤要等一兩秒才看得到東西... 所以「使用心得」主要是速度測試。


附錄 - 大頁面測試使用的網頁:

<html>
  <head>
    <title>A very big page!</title>
    <script language="javascript">
      var startTime = new Date();

      function showElapsedTime() {
        var endTime = new Date();
        var elapsedTime = Number(endTime - startTime);

        document.getElementById("results").innerHTML =
          "took " + Number(elapsedTime / 1000) + " sec";
      }
    </script>
  </head>
  <body onload="showElapsedTime();">
    <p id="results">calculating...</p>
    <p>這裡是很長很長的段落</p>
    <p>重複 n 次</p>
    <p>導致這個檔案長大到 10MB...</p>
  </body>
</html>

星期三, 3月 23, 2011

C/C++: i = i++ + ++i;

這樣的一段 code,結果應該是什麼呢?

答案是「不一定」!

在 C/C++ 之中,operator + 並不是 sequence point。例如,運算式「f() + g()」之中,是 f() 先執行還是 g() 先執行,順序是不一定的(跟編譯器實做有關)。所以「i++ + ++i」之中,有可能 i++ 先作,亦有可能 ++i 先作。

並且,如「i=i++;」這樣的式子之中,i 被指派兩次。「i=」的指派動作可能發生在「i++」的指派動作之前、之後、或之間。

所以,為了節省 debug 耗用的腦細胞,任何程式設計師都不應該寫出這樣的程式碼。

====== 囧rz [分隔線] 囧rz ======

額外一提,「std::cout << f() << g();」這樣的程式碼之中,f() 與 g() 的執行順序也是不一定的。這是由於 C++ 的 operator overload 視為 function call。而 C++ 的 member function 實際上會被轉換成多傳入一個 this 引數的 global function。

例如(以下程式並非合法的 C++ code,只是為了解釋程式的行為):

std::cout << f() << g(); // 1
可能被轉成
std::cout.operator << (f()).operator << (g()); // 2
再被轉成
std::ostream::operator << (std::ostream::operator<< (std::cout, f()), g()); // 3

在上述 3 之中,是「std::ostream::operator<< (std::cout, f())」先執行還是「g()」先執行,順序也是不一定的。

所以,若 f() 與 g() 裡面都有輸出,則有可能先看到 g() 的輸出才看到 f() 的輸出,或是剛好相反。例如:

// 可能性 1:
tmp1 = f(); // 列印 f() 裡面的輸出
std::cout << tmp1; // 列印 f() 的結果
tmp2 = g(); // 列印 g() 裡面的輸出
std::cout << tmp2; // 列印 g() 的結果
// 可能性 2:
tmp1 = g(); // 列印 g() 裡面的輸出
tmp2 = f(); // 列印 f() 裡面的輸出
std::cout << tmp2; // 列印 f() 的結果
std::cout << tmp1; // 列印 g() 的結果

延伸閱讀:http://en.wikipedia.org/wiki/Sequence_point

星期六, 2月 05, 2011

Need More SpeedRAM

最近 4G 的 SO-DIMM DDR3 模組的價錢降低到令人很想買(約 2G 價錢的 1.4 倍),於是我就買了兩條回來插。

因為我手上這台 Dell Studio 1557,CPU 是 Intel Core-i7 720qm,有八個邏輯核心,所以通常我在 make 東西的時候都是 -j16 下去跑。可是編譯一些 C++ 的東西(例如 Google Chromium 瀏覽器)的時候,常常一個 gcc process 就吃掉 500MB 的 RAM,導致有 4GB 的 RAM 都會 Thrashing。尤其是開了一些 Chromium、Firefox、Thunderbird 之類的東西的時候,瀏覽器還有機會被 OOM Killer 殺掉... = =

現在都不會了!真好!

桌機的 4GB 的 DDR3 價錢也降低到很 affordable 了,也許改天可以來買四條 4G 拼一台 16GB 記憶體的桌機 XD~ 噢!桌機的硬碟也快滿了!

星期四, 2月 03, 2011

台灣的女人比美國的豬還不如

不是要貶低台灣的女性,請先看完這篇新聞:

美國男子強姦母豬致豬生病 可能獲刑120年(2011/02/02 12:34)

綜合報導 | 國際中心 | NOWNews 今日新聞網

一名美國農場主人日前發現自己的豬行為異常,因擔心其生病請來獸醫為其診治。檢查的結果卻出人意料,這些豬曾受到性侵犯,農場主人隨即報警。

根據美國密西西比格林伍德警方公佈的消息,獸醫表示這些母豬患有嚴重的陰道炎,並且斷定是由性行為「感染」的。除陰道炎外,其中一些母豬的陰道內還存在傷口,懷疑是暴力性行為所致。警方受農場主人委託,在農場內安裝監視器,希望查出這些母豬是如何遭到性侵犯?

隨後,農場附近一名52歲的男子出現在鏡頭裏,這名男子名叫安德魯•李•納什。監視器畫面顯示,納什在鏡頭下做出了反常的動作,在豬群後面脫下了內褲。 納什的整個作案過程持續了很長時間。犯罪嫌疑人納什被以12條罪名起訴,如果罪名成立,他恐將面臨120年徒刑。

在中華民國刑法中有關妨害性自主罪, 最高只有十年有期徒刑。這不是擺明了中華民國女性的性自主權,比美國的豬還不如嗎?

Updating Seagate Harddisk Firmware under Linux

Actually this is not really about Linux. It's just about when you have no windows and want to update the firmware of the HDD with the official utility.

This article is actually about using the loopback support from grub2 to load the official iso, and the memdisk tool from syslinux to load the disk image inside the iso.

Follow these steps below:

  1. download the official Seagate firmware update ISO image (for example, MomentusXT-ALL-SD24.iso)
  2. put the iso image under /boot (or anywhere else that grub2 can access)
  3. get syslinux, we actually only need the memdisk tool. put that in /boot/memdisk (or somewhere else that grub2 can access)
  4. reboot into grub2 shell
    • upon reboot, keep clicking ESC like crazy, this should bring up the boot entry selection screen
    • when you see that screen, hit 'c' to enter the grub shell (the command prompt)
  5. inside the grub shell, run these commands:
    • loopback loop /MomentusXL-ALL-SD24.iso
      • (change this to the path of the iso image)
    • linux16 /memdisk
      • (change this to the path of the memdisk)
    • initrd16 (loop)/AN-SD24.ima
      • (this may vary, just look for the file with a suffix .ima)
      • (if you don't know the filename, `ls (loop)/` to get a list)
    • boot
  6. now you're inside the official firmware update tool, follow the on-screen instructions.

Enjoy!

星期五, 12月 31, 2010

使用習慣真的不好改變

我在好幾年前(可能有五、六年吧),在幫家人(我媽、我妹、我外公... 等等)整理電腦(例如解毒、重灌...)的時候,都會推薦他們不要使用容易被裝一些哩哩叩叩東西的 Microsoft Internet Explorer,而改用不容易中毒又有一堆擴充套件可以用的 Mozilla Firefox,那個時候 Firefox 還是 2.x 還是 3.x 吧...

在不斷洗腦的過程中,我全家人都逐漸改用 Firefox 作為平常使用的網頁瀏覽器。

在 Google 推出 Google Chrome 瀏覽器以後,由於的確瀏覽速度更快,於是我又嘗試推薦他們改用 Chrome。尤其是我妹使用小筆電,又是跟我一樣會同時開個幾十個分頁的人,Firefox 很明顯的比 Chrome 慢很多。

但是,我發現在嘗試說服了一年以後,他們還是在用 Firefox......

使用習慣真的不好改呀!

星期一, 12月 20, 2010

我發現,我的 blog 有一年沒更新 = =

剛才 po 了「這年頭,依法行政也不行...」以後,才發現上一篇「Cross-Compiling Made Easy - with Gentoo Linux」是一年多前 po 的。

2010/12/20 - 2009/12/06 = 379 天...

有夠混... XD

這年頭,依法行政也不行...

最近有一則新聞,是說一位財經法律系的博士研究生撿到某貧婦兩萬多元,在報案以後,要求貧婦要付三成作為報酬。根據著作權法第九條,在這裡全文引用:

【何柏均、李姝姮、方佳怡╱台北報導】

台北縣一名獨自扶養子女的婦人昨領取2萬1千元生活費,卻不慎將裝有手機、金錢的包包遺失,她趕緊撥打自己手機,一名女子接電話後表示會送到警局;婦人原想包紅包答謝對方,未料對方自稱是法律系畢業,要求十分之三報酬、6300元,婦人雖苦苦哀求「能不能拿少一點?」但對方堅持拿6千元,在旁協調的警察看了不禁搖頭:「現在的人眼中只有錢嗎?」
遺失包包的李姓女子(44歲)昨向《蘋果》投訴,她從事會計工作,幾乎是她獨力扶養念大學一年級的女兒及高中的兒子,為方便照顧子女,選擇在家接案、擔任SOHO族,平均月收入3萬多元。她昨天傍晚騎乘機車去接兒子放學,並領取2萬1千元準備支付水電等雜支,在行經土城市裕民路、捷運海山站附近,掛機車前座吊掛勾的包包突然掉落,遭國立高雄大學財經法律系畢業的潘姓女子(28歲)拾獲。

撿錢者稱法律系畢業
李婦指出,由於遺失的包包裡,除2萬1千元生活費,還有證件、手機、住家鑰匙等財物,立刻以兒子手機撥打自己手機門號,潘女接聽後指稱拾獲其包包,約她於廣福派出所交付,她原本慶幸包包失而復得,欲包紅包答謝,未料潘女自稱是法律系畢業,主動要求6300元、十分之三報酬。
李婦不懂法律,以為自己聽錯了,雙方在警局碰面後,她向潘女求情,說自己一個人撫養小孩,「能不能不要拿3成?」未料潘女堅持一毛不能少,警員聽了也幫忙求情說:「一定要要求這麼多嗎?不要這樣啦!」但潘女卻冷漠地回說:「我去問學校老師可不可以這麼做。」警員聽了也不敢再幫腔,李婦聽了也十分心酸。警方指出,《民法》如此規定,他們只能道德勸說,無權干涉。

「教育到底是怎麼了」
經半個多小時談判,因李婦沒百元鈔,最後潘女才願妥協只拿6千元,李婦心想,「一個孩子每月生活費是6千元,但『遺失』6千元,總比遺失2萬1千元好」,於是給了潘女6千元並致謝,潘女拿了錢頭也不回就離開,讓一旁協調的警察也直搖頭嘆氣。
李婦感嘆說,她一直教導自己小孩要拾金不昧,潘女自稱是法律系畢業,卻沒顧及情理,「現在的教育到底是怎麼了?」她認為法律系教授除教導法律,也應該教導一些道德觀念。
對此,教育專家吳娟瑜感慨地說:「懂得物歸原主代表有良知,但主動說出口要錢,這態度就有失敦厚。」她表示,在人際關係裡,相互扶持、相互關心、善良友愛,才是正確價值觀,但接連發生大學生撿到錢向失主索報酬事件,顯示社會越來越功利、太以錢為重,她給年輕人建議:「不管失主有沒有給酬賞,都不應該主動開口,才是禮貌的表現。」

留置權不應用於弱勢
台大社工系副教授王雲東表示,隨著社會變遷,不可諱言功利比率上升、道德下降,學生容易著眼功利色彩,只問行使留置權違法與否,而忽略此舉是否「道德」。他說,社會功利色彩濃厚當下,若是留置權不再,可能拾獲者更不願意把錢交出來,因此,他認為是否有可能在法律設計上能夠周詳,如留置權是否不要用在弱勢人身上等。
律師廖芳萱表示,只要撿到錢的人有通知失主,或向警察機關報案,就不算侵占,可向失主主張取得一定報酬及留置權,根據《民法》第805條規定,拾得人要在6個月內請求報酬十分之三,若對方未給報酬,拾得人就對遺失物有留置權。

然後,以下是民法第八百零五條的全文:

遺失物自通知或最後招領之日起六個月內,有受領權之人認領時,拾得人、招領人、警察或自治機關,於通知、招領及保管之費用受償後,應將其物返還之。
有受領權之人認領遺失物時,拾得人得請求報酬。但不得超過其物財產上價值十分之三;其不具有財產上價值者,拾得人亦得請求相當之報酬。前項報酬請求權,因六個月間不行使而消滅。
第一項費用之支出者或得請求報酬之拾得人,在其費用或報酬未受清償前,就該遺失物有留置權;其權利人有數人時,遺失物占有人視為為全體權利人占有。

首先,我們想想看為什麼民法中要保障拾得人得請求報酬的權力?試想,當一個人撿到東西的時候,他有兩個選擇:還給失主或據為己有。若他還給失主,則失主可以取回遺失物;若他據為己有,則失主 100% 不能取回遺失物。驅動拾得人將遺失物還給失主的誘因之中,消極的誘因是若據為己有則犯刑法第三百三十七條中的侵占遺失物罪,雖然罰的錢不多,但會因此留下前科;積極的誘因則是民法第八百零五條中,有關請求報酬與留置遺失物的權力:

  • 據為己有:可以得到全部的遺失物,但是有被抓到判刑的風險
  • 還給失主:可以得到至多遺失物 30% 價值的金額,完全沒有風險
若沒有第二條,雖然有風險,可是當報酬(遺失物的價值)夠高的時候,可能會有人鋌而走險。反正要是真的被抓到也只是被罰伍佰元。但是若有了第二條,因為完全沒有風險就可以取得至多 30% 的報酬,所以有更多人會願意把遺失物拿去還。

首先,遺失東西完全是失主的責任。這個東西對於失主來說越重要,那麼遺失的後果也應該越嚴重。遺失物之於失主的重要性,與拾得人完全無關,拾得人也無法影響該物品之於失主的重要性。這些道理有點腦子的人應該都懂。所以,當這個物品的重要性越高,對於失主來說的價值也就越高,那麼失主本應付出更多的報酬才能取回遺失物。

拾得人有要求至多三成報酬的權利,而實際要求多少報酬則看拾得人的心情。若失主覺得報酬不合理,可以跟對方「殺價」。如果一直無法達成共識,最後也可以上法院請法官來決定合理的報酬該是多少。

在本例中,婦人弄丟的是下個月的生活費。如果沒有這筆錢,接下來的生活會過得很艱難。所以對於該婦人來說,該遺失物是相當重要的。若想要及時取回,則應該付出較高的報酬。而對於拾得人來說,把遺失物「賣回」給失主是一樁「獨門生意」。在商言商,本應將利潤最大化。要求最高的報酬合情合理。我認為沒有理由要求拾得人無償將遺失物還給失主,就像我認為沒有理由要求商人以進貨價格出售貨品一樣。我也認為沒有理由在失主付出報酬之前,就能將遺失物取回,就好像我不認為買方在付錢以前,就能獲得商品的所有權。

如果說要用商業競爭法來審判潘女也不合理,因為潘女並不是靠「撿遺失物還給失主再要求報酬」這向業務來賺錢的。

法律不外乎人情,為了避免拾得人直接侵占遺失物,民法保障請求至多三成報酬與留置的權力,是相當合乎人情的。掉了東西能找回來就該是燒高香了,願意把東西還給失主的拾得人更是佛心來的,怎麼能不多給他幾成報酬呢?

反倒是刑法第三百三十七條的罰金少的很不合理,應該也改成至多遺失物價值三成的專科罰金才對。

星期日, 12月 06, 2009

Cross-Compiling Made Easy - with Gentoo Linux

用 Gentoo 最開心的地方,就是它非常的 developer friendly。

交叉工具鍊 - Cross-Toolchain

個人認為這個翻譯很糟糕... 不過要在 Gentoo 下要生出一個可用的 cross-compiler,只需要兩行指令:

$ sudo emerge crossdev
$ sudo crossdev -t ARCH-VENDOR-OS-LIBC

請將 ARCH-VENDOR-OS-LIBC 取代成對應的軟硬體設置,具體請參考 `crossdev -t help`。

不過在這之前,最好先有個本機上的 PORTDIR_OVERLAY. 不然 crossdev 會建立一些檔案根目錄在 PORTDIR_OVERLAY 裡面找到的第一個目錄下。您可以用以下指令直接修改 /etc/make.conf(注意單引號跟雙引號):

$ sudo bash -c 'echo PORTDIR_OVERLAY=\"/path/to/overlay \${PORTDIR_OVERLAY}\" >> /etc/make.conf'

雖然要等一段時間,不過過程可是全自動的!

做完以後,就會得到一整排的工具了。例如 ARCH-VENDOR-OS-LIBC-{gcc,g++,as,ld,strip,...} 等等。

目標檔案系統 - Target Filesystem

基本上也是三個指令,不過要等更久...

$ sudo emerge crossdev-wrappers
$ sudo emerge-wrapper --init
emerge-ARCH-VENDOR-OS-LIBC system -v

然後系統就會出現在 /usr/ARCH-VENDOR-OS-LIBC 目錄下了。注意喔,千萬別把它移走!即使移走也要作個 symlink 回來,不然 cross-emerge 會找不到路徑。

星期五, 12月 04, 2009

接觸不良

由於憂鬱症的關係,我從大約四個月前開始服用 惠氏速悅持續性膠囊(Effexor XR),其主成分為Venlafaxine。醫師開給我的處方劑量,由一開始的每日一顆,逐步增加到目前的每日三顆。

藥本身還算有用,下面做成清單不是為了賣弄我知道 html 的 <ul> 與 <li> 標籤,純粹只是我討厭在一長段文字裡面敘述這種明明做成清單就可以一目了然、寫成一大段就看得不清不楚的概念:

  • 每日 75mg:30% 療效
  • 每日 150mg:50% 療效
  • 每日 225mg:70% 療效

這裡的「療效」指的是,我自認與正常沒有神經病的人相比的相似程度 - 之於我也就是可以在固定的時間固定的事情,以及不會莫名其妙就想些雜七雜八事情的能力。

但是... 雖然醫生有給我開連續處方籤,但是你不能期待一個神經病會自己去拿藥來吃是吧?所以每隔一個月左右,我總會有幾天想吃藥卻沒藥吃的時候(例如現在 XD)。

服用高劑量卻突然「斷糧」的結果,是會有突然停藥的強大副作用 @@ 感覺就好像是類比電視突然被突波干擾,畫面瞬間跳掉又回來那樣。可是這種狀況發生在你的視覺、聽覺、觸覺上。

唔...「為什麼你不去拿藥吃就好了呢?」


btw,照這個比例來講我吃五顆就會變成超人了是吧?