發表文章

目前顯示的是 1月, 2008的文章

Linux Process 1 ~ Tasks Lists

圖片
Process,在一般作業系統的教科書給它的定義是「an instance of a program 」。在 Linux 裡面,對 Process 的 Descriptor 是定義在 include/linux/sched.h 裡面的 task_struct。要注意的是, Linux 裡面是採用 lightweight process 的實作概念,換言之,每個 thread 都有一個 task descriptor,而且每個 task 的 pid 都是獨一的。可是,在 POSIX Thread 的標準裡面規定,一個 process 裡面所有 threads 的 pid 都必須相同,所以在 task_struct 裡面多導入了一個變數,叫做 tgid( task group ID ),在同一個 process 裡面不同的 threads 都有不同的 pid,但他們的 tgid 是相同的(這個事實也告訴我們,當我們在應用程式裡面呼叫 getpid() 的時候,其實回傳值是 tgid 而不是 pid 喔)。 接下來要慢慢研究這個 structure。這個 structure 有點複雜,我們先集中在 Task List 的部分。首先我們來看下面的 Macro~ #define next_task(p) list_entry(rcu_dereference((p)->tasks.next), struct task_struct, tasks) #define for_each_process(p) \ for (p = &init_task ; (p = next_task(p)) != &init_task ; ) 顧名思義,這個 Macro 會將所有的 Process 掃過一遍。每一個存在的 Porcess 都是透過 structure 內部的 tasks( struct list_head )所彼此串起來的。可是有一件很神奇的是,當我們執行 multi-thread 的程式時,我們發現無法透過這個 Macro 來找出除了主線程以外的其他 thread 資訊。對作業系統來說,一個 Process 開再多的 threads 也還是一個 Process,所以在那隻 Macro 裡面是找不到的。那那些被創造出來的 thread descriptor

一次得救,永遠得救

最近被問到關於「一次得救、永遠得救」的看法。就想說趁這個機會,在 Blog 裡面在多開一個分類~「信仰」,包含了自己在神學上的看法、靈修心得、屬靈書籍分享或是聽道的收穫。 「一次得救,永遠得救」之所以這麼令人難以接受,就是因為它太簡單了。為什麼呢?一次得救就可以永遠得救?這不是太便宜了嗎?只要相信、受洗,就可以拿到天堂的入場卷,那麼人又何必如此辛苦奮鬥,勉勵行善呢?相較之下,佛教講求作好事、積功德,在人世間不是更可以散發出美好的人性光輝嗎?而儒家傳統思想裡面,「士,不可以不弘毅,任重而道遠。仁以為己任,不亦重乎,死而後已,不亦遠乎。」這種堅持向善,至死奮鬥的精神,更是令人敬佩。無怪乎 ... 「一次得救、永遠得救」這樣的宗教說法實在是太令人難以相信,或是說太不值得尊重了嗎? 先說我的結論,我相信「一次得救、永遠得救」。 我們來瞭解一下,到底什麼是「一次得救、永遠得救」。並且也看贊成的理由、反對的理由,並且為什麼我會如此信。 加爾文五要義 首先,我們來看看贊成方的說法,在這裡我們以加爾文的理論做為代表,並不是說他是第一個提出這個論點的神學家,而是他整理的比較清楚。加爾文,一位偉大的系統神學家,在他著名的著作「基督教要義」裡面對相關的問題有清楚的介紹,因為著作份量太重了,後人把他在這方面的論點歸納成最著名的「加爾文五要義」 完全無能力(Total inability)或全然敗壞(Total depravity) 從亞當、夏娃墮落以來,人類喪失了向善的本性而抵擋上帝,人類不是沒有自由,但那是作惡的自由(隨己意行做各樣的惡事),而無法認識神、遵行上帝的旨意。 無條件選擇(Unconditional election) 上帝揀選人施行拯救,不是因為有好行為、也不是出於人的信心。乃是憑著上帝永恆的預旨及祂無可測度的智慧來揀選。 有限的代贖(Limited atonement) 基督釘十字架,是為那些在創世以前預先蒙揀選的百姓,而不是為所有的人。 不可抗拒的恩典(Irresistible grace) 人類無法因為任何理由拒絕上帝的救恩。 聖徒永蒙保守(Perseverence of the saints) 凡神所揀選的,神必保守直到永恆,一個也不失落。 這就是著名的鬱金香(Tulip)。很明顯的,所謂的「一次得救、永遠得救」,是屬於「聖徒永蒙保守」的範圍。不過因為這是一整套的理

Variant Arguments

在C/C++(C89)中,有所謂的variant argument(變動引數)這東西。說穿了,就是讓使用者可以輸入不定長度的參數,最著名的例子就是 printf 這個大家都會用的函式。下面就來看看實際上的用法。 首先,在宣告函數上,在所要帶入的參數部分用「...」來表示,如下所示: void func(int, ... ); 這樣就可以讓編譯器不檢查所輸入的參數型態跟數量(但為什麼在 ... 前面還要在多一個參數呢?容後在述)。但是,比較大的麻煩是,我們要如何將所要的參數取出來呢?在 stdarg.h (在 C++ 則是 cstdarg ) 有提供一個好用的型態以及一些巨集,分別列在下面: type: va_list : type for iterating arguments macros: va_start : Start iterating arguments with a va_list va_arg : Retrieve an argument va_end : Free a va_list va_copy : Copy contents of one va_list to another(這是 C99 的標準) 我們先來看看一個實際的例子。下面的函式,第一個參數代表的是總共有 n 個參數(不含他自己),然後把後面所有的參數都印出來(並且假設後面所有的參數型態都是 int ) void func(int n, ...) { va_list args; va_start(args, n); while(n>0) { printf("%d\n", va_arg(args, int)); n--; } va_end(args); } 讓我們看看實際的定義: In stdarg.h ... typedef __builtin_va_list __gnuc_va_list; typedef __gnuc_va_list va_list; #define va_start(v,l) __builtin_va_start(v,l) #define va_end(v) __builtin_va_end(v) #define va_arg(v,l) __builtin_va_arg(v

Linked List in Linux Kernel

Linklist 是最常被使用的一種資料結構,當然在 Link Kernel 中也不例外。下面會介紹在 Linux Kernel 中所使用的 Link List。 當然,按照慣例,排版會按照自己喜歡的格式來進行排 版。 Kernel: 2.6.17 在 Linux 裡面,List 的相關定義函式是放在 linux/include/linux/list.h,而最主要的定義如下: struct list_head { struct list_head *next; struct list_head *prev; }; 很明顯地可以看出,這是一個 double linked list 的架構,但是看起來跟一般我們寫程式所實作的方式並不相同。如果是我們設計的話,我們可能會設計成這個樣子: struct my_list { void *myitem; struct my_list *next; struct my_list *prev; }; 其中 myitem 就是用來存每個 list node 的 Data ,而且為了要泛用,所以使用了 (void *) 這樣的資料型態。 這樣的設計跟 Linux Kernel 的設計到底有什麼差異還不清楚,或許是個人風格吧~ (我同事有發表相關的意見,他認為用 Linux Kernel 的那種作法可以將 list 跟 data 完全的切割,而使用我一般的作法,固然可以達到 list 的效果,但是在參數傳遞上,變數名稱將會是 struct my_list,而無法直覺的看出來實際的資料型態...well ...見仁見智囉) Linux Kernel list 的使用方式,我們看下面一個範例: #include &lt stdio.h &gt #include &lt stdlib.h &gt #include "list.h" struct kool_list { int to; struct list_head list; int from; }; int main(int argc, char **argv) { struct kool_list *tmp; struct list_head *pos, *q; u

平敦盛

平敦盛,生於1169年,死於1184年3月20日(一之谷戰役)。會特別記錄這個人是因為下面這首歌曲: 思へばこの世は常の住み家にあらず。          草葉に置く白露、水に宿る月よりなほあやし。      きんこくに花を詠じ、栄花は先つて無常の風に誘はるる。 南楼の月を弄ぶ輩も月に先つて有為の雲にかくれり。   人間五十年、下天のうちを比ぶれば夢幻の如くなり。   一度生を受け、滅せぬもののあるべきか。 留念今生並非無法忘懷生前之事 有如置於草葉上之露水 寄宿於水中之月 詠嘆京國之花,於榮華之前誘於無常之風 玩弄南樓之月,此輩則似浮雲消逝於黃昏之中 人生五十年 與天下相比,如夢似幻 既一度有此生,又豈有不滅之理 這首歌曲是「幸若舞」的「敦盛」,之所以這麼有名,主要是因為這是織田信長最喜歡的歌舞。相傳在桶狹間前夕信長跳完了這一段舞後,對今川義元發動奇襲;以及本能寺之變的時候,信長也是舞完了這一段「敦盛」,而後步入火舌之中。 「敦盛」這段故事,典故出於日本第一部合戰傳奇「平家物語」,講的是平家的小將平敦盛,在海邊被源家部將熊谷直實對決斬殺的史實:話說熊谷早就聽說過敦盛的大名,據傳敦盛文武兼資,又是當代吹笛名手之一(當代吹笛名手不是姓藤原就是姓平),是平家年輕一代的佼佼者,但是等到交鋒後才發現敦盛年輕到可以當自己兒子(好像是16歲)!於是熊谷的惻隱之心油然而生,本想饒過這個年輕到不可能和源家上代有仇的小孩,但是眼看其他源家人都追上來了,自己不下手,恐怕還得揹個通敵的黑鍋,正在左右為難之際,平敦盛反而催促這名部將下手,蓋敦盛已經看破了武家的宿命即是如此。等到熊谷砍了敦盛的頭,在遺物中發現笛子,突然想起昨天晚上還聽到敵陣中傳來優美的笛聲,看來恐怕就是敦盛的傑作呢,一念至此,當下頓悟人生無常、枯榮轉瞬之理,於是熊谷就出家當了和尚,給後世流下一段令人嘆息的故事。 不由得聯想到平家物語的序之卷... 祇園精舎の鐘の声、諸行無常の響きあり。 沙羅双樹の花の色、盛者必衰のことわりをあらはす。 おごれる人も久しからず、 ただ春の夜の夢のごとし。 たけき者もつひにはほろびぬ、 ひとへに風の前の塵に同じ。 祇園精舍的鐘聲、響徹著警喻諸行定無常律 沙羅双樹的花色、道盡天下盛極必衰的真理 而驕奢者豈能久長 到頭來有如春夜般夢一場 縱使英雄蓋世終將為之一傾 猶如風前土煙塵

Google 大學?

下面是中國時報 2008.01.15 的一篇報導 //-------------------------------------------- 網路時代,只要在網路搜尋引擎Google鍵入關鍵字就能輕易查到相關資料,英國布萊頓大學媒體研究教授塔拉.布拉芭蓉便形容Google是「心智的白麵包」,但她也指出,網路正製造出一個仰賴不可靠資訊生存的學生世代。  據英國《泰晤士報》14日報導,有18年大學教學經驗的布拉芭蓉本周將在布萊頓大學授課。她認為,資訊取得容易使學生的好奇心鈍化,同時抑制了辯論風氣。  此外,許多剛進入大學的學生根本分辨不出網路上張貼的軼聞與毫無根據的資訊之間有何差異,卡拉芭蓉稱這種教育是「Google大學」教育。   英教授批網路資訊不全正確  卡拉芭蓉指出,艱難的問題能從Google找到簡單答案。但學生無從分辨這些答案是來自嚴謹的期刊論文或者只是粗淺的概念,Google的資訊包羅萬象,但未必是有營養的內容。  布拉巴蓉的疑慮與《業餘愛好者的教派》(The Cult of the Amateur)一書的作者安德魯.基恩的看法不謀而合。基恩痛批「線上業餘主義」,他在書中寫道:「現今媒體正在把這個世界撕碎成十億個個人化的真理,每個都看似合理而且等值。」  布拉巴蓉教授指出,學生雖身處在資訊時代,但他們欠缺正確的資訊,他們上到維基百科網站找資料無可厚非,因為唾手可得。可是由網友編撰內容的維基百科曾被批評充斥不正確資訊,甚至它的創辦人之一拉瑞.桑格在去年離開這個網站之前,曾說維基已經「無可救藥」。   資訊易得 學生不作過濾  由於傳統圖書館式微、藏書減少及圖書管理員人數下降,從Google等媒體平台尋找解答天經地義,然而箇中要訣就是學習如何善用網路工具。  布拉巴蓉認為,教師必須訓練學生成為積極批判的思想家,讓學生具備詮釋及過濾網路資料的能力,而不是照單全收。 //-------------------------------------------- Google 的確很好用,但是所查出來資訊的正確性誰也無法保證。在所謂Web 2.0 的年代,人人都有辦法發表自己的智慧結晶,甚至也可以及眾人之力輕易的編出百科全書,但有誰能為這些在網路上的資訊把關呢?事實上,這篇報導是真的?還是假的呢?

三分鐘看完中國歷史

在網路上看到的文章,挺有意思的~ 盤古說:我開 女媧說:我補 共工說:我撞 神農說:我嘗 精衛說:我填 夸父說:我追 后羿說:我射 嫦娥說:沒射著! --------------------------------------------------------------- 黃帝說:我們做什麼 堯說:我讓 舜說:我也讓 禹說:咱爺們怎麼辦? 啟說:讓他們求! 桀說:好玩 湯說:造反有理了 夏亡了…… --------------------------------------------------------------- 紂說:痛快 武王說:我也反了 商亡了…… --------------------------------------------------------------- 幽王說:點火 褒姒說:刺激 周也亡了…… --------------------------------------------------------------- 干將說:我鑄 專諸說:我舞 荊柯說:我刺 瀛政一躲:沒刺著…… --------------------------------------------------------------- 始皇說:我修 姜女說:我哭 陳勝說:有種 項羽說:我舉 劉邦說:我斬 秦亡了…… --------------------------------------------------------------- 孔子說:我仁 孟子說:我義 老子說:我無為 莊子說:我逍遙 韓非子說:把他們全抓了 --------------------------------------------------------------- 張良說:我出謀劃策 韓信說:我統帥三軍 蕭何說:我運籌帷幄 高祖說:老婆,怎麼辦 呂后說:全喀嚓了 --------------------------------------------------------------- 文景說:我治 武帝說:我興 光武說:我中興 獻帝說:我說了不算 --------------------------------------------------------------- 張騫說:我通 班超說:我也通 蘇武說:通個屁! ----------------------

GCC 詳細編譯步驟

使用 GCC 來編譯程式看起來相當容易,如下面的例子: [neokent@FEDORA Projects]$ gcc hello.c -o hello [neokent@FEDORA Projects]$ ./hello Hello World! 但 GCC 到底做了些什麼事呢?多加一個「-v」的參數以後來試試看(下面是實際跑出來的例子,但是為了美觀起見,稍微修改了一下排版) [neokent@FEDORA Projects]$ gcc -v hello.c -o hello 使用內建 specs。 目的:i386-redhat-linux 配置為:../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-languages=c,c++,objc,obj-c++,java,fortran,ada --enable-java-awt=gtk --disable-dssi --enable-plugin --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --with-cpu=generic --host=i386-redhat-linux 執行緒模型:posix gcc 版本 4.1.2 20070925 (Red Hat 4.1.2-33) /usr/libexec/gcc/i386-redhat-linux/4.1.2/cc1 -quiet -v hello.c -quiet -dumpbase hello.c -mtune=generic -auxbase hello -version -o /tmp/ccdKC85q

Paging Structure in Linux

圖片
為了符合各種架構的處理器(包含 64bit 處理器),Linux 所採用的架構是 4-level paging architecture。架構圖如下: 四層架構分別為: Page Global Directory Page Upper Directory Page Middle Directory Page Table 當處理器是 32bit 而且 PAE disabled 的情況下,PUD 和 PMD 是不使用的。 Paging Implementation in Linux Kernel 接下來要看 Linux Kernel 內部關於 Paging 的實作方式。 Kernel Version: 2.6.17 Arch: i386 首先,來看看 page 在Linux Kernel中的定義。 /linux/include/asm-i386/page.h: #ifdef CONFIG_X86_PAE typedef struct { unsigned long pte_low, pte_high; } pte_t; typedef struct { unsigned long long pmd; } pmd_t; typedef struct { unsigned long long pgd; } pgd_t; typedef struct { unsigned long long pgprot; } pgprot_t; #define HPAGE_SHIFT 21 #else typedef struct { unsigned long pte_low; } pte_t; typedef struct { unsigned long pgd; } pgd_t; typedef struct { unsigned long pgprot; } pgprot_t; #define HPAGE_SHIFT 22 在這裡我們可以看到 page entry 和 page directory 的定義。特別要注意的是 pgprot_t,它所代表的含意是「the protection flags associated with a single entry」。至於HPAGE_SHIFT指的是當

IA32 Memory Management

圖片
下面這段資料來自於 「Intel® 64 and IA-32 Architectures Software Developer’s Manual」 The memory management facilities of the IA-32 architecture are divided into two parts: segmentation and paging. Segmentation provides a mechanism of isolating individual code, data, and stack modules so that multiple programs (or tasks) can run on the same processor without interfering with one another. Paging provides a mechanism for implementing a conventional demand-paged, virtual-memory system where sections of a program’s execution environment are mapped into physical memory as needed. Paging can also be used to provide isolation between multiple tasks. When operating in protected mode, some form of segmentation must be used. There is no mode bit to disable segmentation . The use of paging, however, is optional. IA32 Segmentation 和 Paging 關係圖 簡單來說,Segmentation 是處理器上的機制,每一個正在處理器上運作的 task (應該用「任務」呢?還是用「程式」好呢)都會有他自己獨立的 Segment。而所謂的 Logical Address 指的就是處理器上 Segment 的位址。這個機制最大的好處在於保護每個 task 的記憶體區塊不會互相干擾。 在 linux

IA32 Paging Architecture

圖片
Paging Unit:將線性位址(Linear Address,或稱作虛擬位址Virtual Address)轉換成實體位址的功能單元。 在 i386 的系統裡面,因為是 32-bit CPU 的關係,所以最多只能定址到 4GB 的虛擬記憶體。定址方式總共有四種: 4KB/page without PAE enabled 4MB/page without PAE enabled 4KB/page with PAE enabled 2MB/page with PAE enabled 什麼是 CR3 Register points to page table 什麼是 PAE 呢? 在 Intel 的 64 and IA-32 Architectures Software Developer's Manual 裡面給的定義如下: 「Physical Address Extension. Physical addresses greater than 32 bits are supported: extended page table entry formats, an extra level in the page translation tables is defined, 2-Mbyte pages are supported instead of 4 Mbyte pages if PAE bit is 1. The actual number of address bits beyond 32 is not defined, and is implementation specific.」 簡單來說,就是一套讓32bit CPU能夠定址到大於 4GB 的記憶體位址。在Intel的實作裡面,就是把原先 page table 中的 2 個 entries 當成一個 entry 來用,所以從原來的 32bit 延伸到 64bit。不過這裡要注意的是,雖然有 64 bit,不過其實只使用了 36 bit,剩下的 28bit 為 reserved,也就是說記憶體只能支援到 64GB。 Page Directory Entry & Page Table Entry 的欄位詳細資料 下面兩張圖是 IA32 中規定,在 Page Directory Entry 和

刁鑽數學難題?

圖片
上個月在網路上看到一則新聞,「刁鑽數學難題,難倒國中師生」,突然一時興起,想在無聊的DEBUG之餘拿來放鬆心情,不過做完以後心情有點沈重...先來看看新聞報導好了。 ======================================================= 〔記者何玉華/板橋報導〕台灣學生數學能力在國際評比中獲得第一名,但永和國中三年級日前剛結束的第二次段考,一題數學考題難倒九成八學生,家長質疑太難,超過國中能力範圍;縣議會金蘭會議員昨天邀來土城、板橋區八位數學老師試作,時間滴答滴答過六分鐘後,終於有兩位老師解答成功。 永和國中出題老師則透過教育局表示,出題時也思考過學生的答題能力,因此前半段多是難度不高的選擇題、填充題,只有最後的三題難度較高;當初也考慮到時間的排擠性,因此安排在最後回答,避免學生浪費作答時間。 縣議會金蘭會議員金介壽、黃林玲玲、李肇南、鄭世維、黃桂蘭昨天舉行「考學生?烤老師?通通倒」記者會;金介壽說,接獲不少永和國中學生、家長反映,段考有一題數學題目超難, 有學生家長在大學理工科系任教,每題都會,唯獨這一題不會 , 甚至是老師講解也「掛」,一整節解不出來,邊解邊罵。 黃林玲玲說,他把題目拿給就讀清華大學應數研究所的兒子看,兒子雖然成功解答,但表示不知道現在的國三生是不是已經有能力解題;她強調,考試不是要考倒學生, 如果題目有三分之一的學生不會,老師就要思考,要讓孩子了解學習的能力可以解決問題 。 鄭世維、李肇南質疑,是否課堂上教得越難,要讓學生去補習才學得會,他們痛斥這是「教改的失敗」;黃桂蘭也表示,段考是要幫孩子提升數學的能力,不是要考倒學生,要求各校應該要有教學領域的審題制度。 教育局主任秘書洪啟昌表示,各校目前都有審題跟出題的制度,只是實施的方法略有不同;永和國中除出題老師外,還有另一位老師就配分審題,只是沒有進行實質題目討論。 ======================================================= 在發表感想之前,先來看一下題目吧。題目如下: 請算出下列黃色區域的面積。 恩,看起來好像有點難,但這真的無法可解嗎? 對一般理工科的大學生來說,起碼可以用微積分來算吧!當然了,我們不能要求國中生使用微積分這樣不合理的技術,那應該要怎麼作呢? 看看上面的輔助線圖,答案其實就是正中央的綠

很壞很壞的駭客

此事件發生在德國一個名為 stopHipHop 的 IRC channel 上 地點:IRC-Channel #stopHipHop (譯者註: 依名稱來看,這個 IRC 交談室的設立人應該不太喜歡 HipHop 曲風) 角色介紹: Elch~ : 推斷可能是 IRC 交談室 #stopHipHop 的設立者 bitchchecker~ : 號稱"厲害"的"駭客" (推測可能是個 HipHop 迷) Metanot~ : 聊天插花者 #1 HopperHunter|afk~ : 聊天插花者 #2 He~ : 聊天插花者 #3 (以下為 #stopHipHop 的 log 紀錄檔) -------------------------------------------------------- QUOTE * bitchchecker (~java@euirc-a97f9137.dip.t-dialin.net) Quit (Ping timeout#) (Log 紀錄) (不明原因 time-out) * bitchchecker (~java@euirc-61a2169c.dip.t-dialin.net) has joined #stopHipHop (Log 紀錄) (bitchchecker 登入 IRC) bitchchecker~ 你為什麼踢掉我? bitchchecker~ 可以解釋一下嗎? bitchchecker~ 回答我呀! Elch~ 我們沒踢掉你啊! Elch~ 是你自己 ping timeout 的 (紀錄): * bitchchecker (~java@euirc-a97f9137.dip.t-dialin.net) Quit (Ping timeout#) bitchchecker~ 什麼 ping 啊.. 老兄 bitchchecker~ 我電腦的時間是正確的... bitchchecker~ 我還設定了日光節約時間耶! bitchchecker~ 是你踢掉我的啦! bitchchecker~ 承認吧!你這個王八蛋! HopperHunter|afk~ lol 哇哈哈! HopperHunter|afk~ 你這個呆瓜... 哈哈日光節約時間!.... bitchchecker~ 你給我閉嘴!!我

程式設計師該有的心態

以下有部分內容擷取自網路上的一篇文章:「學程式的人不能不看的文章」 看到這篇文章的時候,著實讓我深思了不少。程式不能單單只要求要寫的正確,不加思索就直接 coding,花點時間想想往往有更好的作法,就像打橋牌的人,當夢家把牌攤下來的那一刻就直接出牌的莊家,大概不是什麼太厲害的高手。靜下心來想想,往往有更出人意料的解答。畢竟,我們是工程師,是要解決問題的專家,而不應該是聽命行事、一個命令一個動作的工匠。 Question: 請寫一個函式來計算 1-2+3-4+5-6+7......+n 最直覺得想法如下: long fn(long n) { long temp=0; int i,flag=1; if(n<=0) { printf("error: n must > 0); exit(1); } for(i=1;i<=n;i++) { temp=temp+flag*i; flag=(-1)*flag; } return temp; } 非常簡單而明瞭,但是,這是好答案嗎?來看看下面的作法 long fn(long n) { long temp=0; int j=1,i=1,flag=1; if(n<=0) { printf("error: n must > 0); exit(1); } while(j<=n) { temp=temp+i; i=-i; i>0?i++:i--; j++; } return temp; } Better! 少了不少乘法的運算,畢竟在計算機的世界,加法運算來的比乘法還要快~ 但,下一個答案呢? long fn(long n) { if(n<=0) { printf("error: n must > 0

緣起

我總算決定寫 Blog 了... 我一直在找一種可以做好 Knowledge Base 的軟體,但是卻總是沒有找到,不是要錢的(我喜歡找免費軟體),不然就是只能做文字記錄,再不然就是太難以使用,而且我也會擔心版本的問題。後來我開始看到有人使用 Blog 進行類似的紀錄,覺得效果看來還不錯,於是,2009年1月1日,我的 Blog 開張了~ 雖然說本意是要進行 Knowledge Base 的紀錄跟管理啦,不過既然都申請了,那就什麼都寫寫吧,不管是天馬行空的胡思亂想、靈機一動的閃光、嚴肅的靈修分享、不吐不快的心情點滴,都會出現在這裡,當然,頻率不會太高就是了。 那麼,就開始吧,但願能夠持之以恆~