2013年11月13日星期三

一手成交增 樓市勢調整?

2013年11月14日

一手成交增 樓市勢調整?

近月來發展商積極推售一手樓宇,不但搶去樓市的焦點,也可能成為「推跌樓市的最後一根稻草」【註1】。歷年一手樓銷售數字的變化,究竟與樓市走勢是否存在密切關係?是次研究部透過土地註冊處一手住宅買賣數字,與讀者探討這課題;另外,本欄亦將透過樓市市寬指標,與讀者更新近期樓市的表現。
近月多個發展商減價(「減辣」)加快推盤,究竟這對樓價後市表現有何玄機?不難理解的是,發展商是不折不扣的市場人士,也是market maker,對市場(訊息)的掌握,以至對樓市前景的看法,往往較普羅市民更準繩。
消耗市場購買力
當然,發展商加快推售一手樓盤,不一定代表看淡後市(但看淡後市卻必會加快推盤);惟多個發展商積極售樓,即一手銷售數字攀升至高位,往往意味着消耗不少的購買力,為樓價後市表現構成一定的壓力,情況與股市IPO活動及恒指走勢存在着密切關係相若。
那麼,一手住宅樓宇買賣數字,是否支持這論點呢?
從土地註冊處歷年的一手住宅買賣數字,可發現從多個層面與樓價表現有密切的關係,其中之一便是12個月累計一手買賣宗數按年變化(下稱一手買賣宗數變化)。
一手買賣宗數變化與樓價按年走勢亦步亦趨【圖1】。事實上,兩者變化的相關系數達0.52的頗高水平,而且前者(尤其在變速見頂時)往往領先樓價走勢約3至7個月(註:不難想像,一手買賣涉及金額的按年變化同樣與樓價存在密切關係)。
一手宗數與樓市關係密切
換言之,一手買賣宗數變化見頂後,樓價的升勢往往約在半年內出現逆轉;唯一的例外是2010年3月,當時一手買賣宗數變化與樓價按年變化同步見頂。隨後(發展商)始料不及的是,聯儲局於2010年8月27日暗示推出QE2,令樓價升勢在2010年9月後再度加速,並與一手買賣宗數變化曾出現一段時間的背馳。
至於目前市況,一手買賣宗數變化於2012年10月見頂(註:巧合的是,特區政府於10月27日推出新一輪調控樓市措施,背後有何玄機?),樓價的升勢則在今年2月(即4個月後)見頂。隨後兩者的增長速度持續較慢,而一手買賣宗數變化踏入7月後,更按年出現負增長,即過去一年發展商累計售樓宗數的按年變化,較去年同期為小。
由於一手買賣宗數變化增速持續向下,仍未呈見底回升的迹象,意味樓價的按年升勢,有進一步放慢的機會,甚至較後時間出現負增長(即樓價按年錄得跌幅)。
一手金額佔比領先樓價
值得補充的是,以往一手買賣宗數變化跌至-40%至-60%便會見底(目前讀數為-35%);不過,見底後一手買賣宗數變化速度有時可於低位橫行一段頗長的時間才回升,例如2005年3月至2006年6月,而期間樓價的按年變化可以持續向下。
除一手買賣宗數變化外,一手買賣涉及金額佔總買賣金額比率(下簡稱「一手金額佔比」),與樓價變化同樣有一定密切的關係【圖2】,一手金額佔比攀升至高位並掉頭回落後,樓價的升勢往往在5至10個月內出現逆轉。
至於最近一次一手金額佔比見頂回落是去年第二季初,較樓價升勢速度見頂早約10個月出現。同樣地,由於一手金額佔比持續反覆向下(目前讀數為25%),預料樓價的按年變化仍有進一步回落的空間。
綜觀以上的分析,不難發現,發展商賣樓的步伐往往與樓價變化有着一定的密切關係,惟背後的關係,究竟是發展商有「先見之明」,或市場購買力被發展商吸去(乾),抑或兩者因素皆然?暫時仍不得而知。
無論如何,從目前一手買賣宗數變化和一手金額佔比的趨勢持續向下,加上這兩項指標見底後,樓價往往仍然滯後數個月才會回升。故此,從一手數銷售的角度來看,預料樓價按年,仍有進一步向下的機會。
以下是從樓市(分區)指數及樓市市寬的角度,剖析近月樓市的表現【註2】。
從整體或分區樓價指數的走勢可見,今年4月後樓價大致處於反覆橫行的格局【圖3】,其中新界東的樓價卻創下去年10月28日以來的新高水平。整體樓價橫行某程度反映「辣招」雖抑制樓市的升勢,但樓價看似暫沒有太大的沽售壓力,令其表現處於拉鋸的局面(當然,發展商近日開始加快賣樓步伐,會否打破這悶局有待觀察)。
樓市市寬方面:
屋苑樓價高於10周移動平均價比率:統計全港100個屋苑樓價高於10周移動平均價的比率,雖然從低位略為回升至11月初60%的較高水平,惟比率仍未能擺脫一浪低於一浪形態,並與樓價指數呈背馳【圖4】。換言之,過去近8個月內,雖然樓價指數橫行,但100屋苑樓價高於10周移動平均價的數目反覆減少;往後除非此比率能突破前高位(即約90%),否則背馳情況持續,預料最終將為樓價指數帶來下跌的壓力。
三個月平均升/跌(A/D)線:A/D線於9月中反彈至+9的水平,即過去3個月內屋苑呎價錄得上升的屋苑較下跌的多9個【圖5】;隨後A/D線再度向下,於10月27日後更跌回零水平之下,即過去3個月屋苑呎價下跌的較上升的為多。由於A/D線再度回落至零水平之下,且同樣地與樓價指數呈背馳,料樓價仍存在下調的壓力。
屋苑樓價偏離一年新高/新低平均百分比:屋苑樓價高於一年新低平均百分比,自今年2月初便開始反覆下滑,反映樓價距離1年低位的幅度持續縮減中。截至11月3日,此比率已跌破一成臨界水平至+9.6%,創21個月以來新低,預料樓價指數有回落空間。至於屋苑樓價低於一年新高平均百分比,仍在5%較中性的位置徘徊。宜留意這比率隨後會否同樣升穿一成的臨界水平,果如此,預料樓價將有較深度的調整【圖6】。
註1 見2013年5月2日【投資分析】「樓市陷入較長調整期」及2013年9月12日「推跌樓市的最後一根稻草」。
註2 樓市市寬指標的介紹及其計算方法,可參閱附註1和2013年8月1日「港島區樓價率先回落玄機」。
分析員:呂梓毅

2013年10月17日星期四

聯繫滙率三十載 香港優勢不復再

2013年10月18日

聯繫滙率三十載 香港優勢不復再

聯滙三十周年,金管局搶先撰文,揚言死守。有些行家識做歸邊,成為官方喉舌;已退的行家、學者更為識做,歸邊上面成中央喉舌,指「人」勢所趨,「港」將玩完。此說跟「發牌事件」一樣:表面上口口聲聲無政治考慮,骨子裏徹徹底底的政治計算。
在下一名經人,考慮的不是政治現實,而是怎樣最好──對港人的整體福祉最好。
近日有記者問聯滙何去何從。答曰:視乎你問聯滙的實際何去,還是問港紙之最佳何從。這好比問本港的民主前途:問香港會否終有真正民主,與問真正民主是否對香港最好,是兩個問題。如果寫評論動輒只顧「政治現實」,可將腦袋放於屁股,揣摩上意是了。
際此周年,官者陳腔濫調,將死守言論以人肉錄音機式反覆重播,實無評論價值。至於坊間的退休人士以至所謂學者,則對滙率經濟認識不深,有的更屬「學術外行」,只懂由盤古初開講起港幣歷史,然後不清不楚地跳到掛人仔結論,當中未見嚴謹推論,而實證亦流於表列數據層次。請君好好讀讀滙率經濟罷,當中的實證功夫相當艱深。
兩端最好 切忌中間
際此周年,在下要寫,也是陳腔濫調。緣何?滙制好壞,近十餘年幾有學術定論,再寫也難有新意。
滙率大師Jeffrey Frankel早在1999年已幾乎以定調式的口吻寫道:No single currency regime is right for all countries or at all times(NBER WP 7338)。
滙率制度不外乎是貨幣政策的其一選擇,必須因應環境而變。金管局指聯滙直至永遠,好比儲局官員聲稱QE無限期,是央行以溝通作為影響預期的一種手段,明知是大話。官講就信,只能反映信者之幼稚;至於官云亦云者,則只暴露其對貨幣政策之無知。
滙率制度怎樣才最好?學界其實大致也有定論:兩端最好,切忌中間。大意是指,一是全浮動,一是全固定,最忌半浮動,因為半浮動者多不透明,學界稱dirty float,最易受人衝擊。
1990年代的歐洲滙率機制解體及亞洲貨幣逐一倒下,就是衰正此瓣。由是觀之,那些掛一籃子的主張其實很危險的。只要炒家看準金管局倉裏不足之貨幣,大量買之並沽港紙,央行不夠貨派,籃子即可收檔。若如大教授般建議掛一籃子物品,則更有趣,屆時金管局不是儲美金而是變成儲物倉,有各式各樣的食品、掃把等……
那末兩端而言,固定好還是浮動好?那要看情況了。弱幣掛強幣如小孩拖住大人,是無力的表現。貨幣是白紙印出來的,價值建基於市民對政府的信任。在欠缺信任時,貨幣貶值,當然是掛鈎最好。但若無此問題的話,長期掛鈎便會錯價(misalignment)。
稍懂經濟者必定同意除市場外,無人有資格說7.8是合不合理的滙率水平。只有浮動,合理、正確的滙價才會出現。錯價帶來的後果,無大不了,達不到最佳經濟狀態而已。惜港府重用的經濟學家,信奉市場但卻支持干預滙率這價格,政治令學術人格分裂。
貨幣政策 死跟美國
更有趣是,掛鈎美元不是無貨幣政策,只是完全認同並徹底跟隨美國的貨幣政策。記得金管局、財政司乃至行政長官均曾對美國QE甚表不滿,既然不認同人家的做法,何解還要死跟其政策?
記得1974年冬港紙脫鈎英鎊,當時正值英鎊危機,脫得很對。適逢美國總統尼克遜大力干預聯儲局,貨幣政策走向失控,終致雙位通脹,驀然回首,當時脫英鎊而不改掛美元,也屬明智之選。及至1980年代初前後聯儲局終知錯而改,伏爾克降服通脹,反之港紙因本土前途問題遽貶,當時掛美金穩住滙率,也是英明。
誠然三十年來的聯滙當中,頭十年(即1983至1993年)是最為恰當。其時還歷六四,及隨後的大舉移民潮,穩住民心乃當務之急。不過,及至第二個十年(1993至2003年),聯滙是否最好,回頭看來是兩睇了。這十年間,本港的政、經、社皆大亂,先有1997年這不明朗因素,後有金融風暴、樓價大冧、恐怖襲擊乃至沙士爆發。從政治角度看,聯滙穩住民心;但從經濟角度看,較諸肯脫美金而貶值的其餘三小龍,本港顯然輸蝕。
去年6月,拙作〈十五周年齊苦笑 福去禍來因自招〉已清楚論述,今只重抄九【圖】。
1993至97年,先有歐美衰退熱錢大量湧亞,炒起資產;後有外來衝擊資金逃走,香港是金融中心,不能如馬來西亞般落閘放狗不讓錢走,大進大出,資產價格大上落。一價定律(Law of One Price)下,股、樓、物價、工資統統也大上落。
滙率是一地之價,若當時1997年前讓港紙先升值而後再貶值──那怕是如韓圜般大幅貶值一半,無錯,該刻很痛,但卻是短痛代長痛,毋須任由各類本土價格慢慢跌,而由滙價代為快快貶。這個理論毫不新鮮,佛利民早就提到了。無怪乎如九圖所見,本港在各方面都較衰。
及至第三個十年(2003至2013年),民怨雖仍依舊,但政、經、社三方面未見大亂;固然,往後有無不敢講。這十年間,「衝擊」剛剛相反,大進居多;僅海嘯時見流出。所有本來掛美元的亞太貨幣都浮動了,包括人仔。
1993至97年在2009至13年重演,結果,整個亞太都因而「受惠」而樓價飛升,但以本港最勁。聯儲局現在嚷要收水了,管他最終未必收得成,但效果亦如1997年單邊加息一次(僅1/4厘)一樣,引發危機。第二個十年沒有脫鈎,因多事之秋都算數了;但第三個十年仍錯過時機,實難原諒。
既然聯滙的弊病在於「一地之價」不因錢進錢出而變,從而將波幅全數傳入本土,按此邏輯,改掛人仔根本無濟於是,原因有三。第一,這不外是由輸入美國貨幣政策,改為輸入大陸貨幣政策。有論據能推證大陸的利率政策比美國的更適合本港嗎?未見。第二,由輸入美國政策的副作用轉為輸入大陸的,可能更糟。
改掛人仔 未必着數
說掛美元輸入美國通脹,改掛人仔只是換了輸入更高的大陸通脹。輸入通縮的情況一樣。第三,美元兌人仔滙價一直過分穩定,假使改掛人仔,美電滙價大抵也不怎行,這又如何發揮調節功能呢?
掛人民幣,即使人民幣未對外流通,操作上是可行的,並非如金管局指般不可行。只要將港幣的美元滙率跟足人仔,就已掛鈎,目前實在看不到任何困難;但這非最佳。
目前大陸仍資本管制,跨境流僅限於因貿易衍生的資金(理論上如是,實際另回事),其滙率按貿易加權的一籃子貨幣,並無不妥。不過,香港做的不單是貿易,還有金融。
純學理講,單按貿易而加權一籃子貨幣予港紙掛鈎,只能對應因貿易而生的資金進出,但對外來投資、投機性的資金則無顧及。香港作為國際金融中心,後一類資金不少。
聯不聯滙,考慮重點還在於究竟錢在本港,是主要扮演着交易功能還是儲值功能。隨着環球貿易愈一體化,生產鏈動輒經多個過家,貿易量對個別地方的滙率敏感度(即「彈性」)已大不如前,反而環球性的因素則愈見重要。這在周期尺度上就更為明顯:近十年觀察到的,是海嘯前不少貨幣升值但貿易擴張;海嘯時則剛相反,貶值貿易縮;海嘯後的近幾年,又回復至幣升貿易增。這現象幾乎舉世皆然。
雖說本土價格也見類似剛述貿易脹縮的現象,但論貿易與價格誰較對滙率敏感,數據上十分清楚──價格。
歸根究柢,究竟對港人而言,是穩定貿易還是穩定價格(樓價、物價)較為重要?考慮之際還須銘記上段所推,穩定貿易的效果已大不如前。
究竟我們定位是貿易中心,還是金融中心多些?前者帶來貿易所衍生的資金,後者則帶來投資資金(包括熱錢)。這些問題倒該問香港人。港府不顧民生福祉便一錘定音,與發牌一樣,無異與民為敵。
參考:本欄〈十五周年齊苦笑 福去禍來因自招〉一文刊2012年6月29日《信報》
交通銀行(香港分行)環球金融市場部

2013年10月16日星期三

有關聯繫滙率制度常見問題

2013年10月15日

有關聯繫滙率制度常見問題

■在聯繫滙率制度(聯滙制)下,美國的寬鬆貨幣政策及弱美元是否引致近年香港通脹上升的主因?
香港通脹受多項內部及外圍因素影響。聯繫滙率並非推高香港通脹的主因。近年,受到食品及商品價格急升等全球因素影響,香港通脹上升。事實上,在2011年港元兌人民幣貶值4.7%,但同期全球商品價格則上漲26%。隨着全球商品價格略為穩定下來,香港通脹亦由2011年的5.3%,逐步回落至2012年的4.1%。
此外,由於香港在服務項目的支出高於商品,商品(包括進口商品)只佔香港消費籃子約四分之一,因此滙率並非推高香港通脹的主要因素。
應注意的是,雖然香港一些鄰近經濟體系沒有採用固定滙率制度,但她們近年仍面對極大的通脹壓力。以新加坡為例,即使其貨幣在2012年兌美元升值約6%,同期新加坡的通脹率為4.6%,高於香港。新加坡的例子說明港元兌人民幣和其他非美元外幣貶值並非香港近年通脹較高的主因。
■浮動滙率制度可否解決香港物業市場過熱的問題?
資產價格變動受到很多不同因素影響,滙率只是其中一個因素。物業價格會因應利率、人口結構、土地及房屋供應,以及家庭收入前景等因素改變。很多實行較具彈性的滙率制度的新興經濟體系在過去幾年亦同樣要面對資金流入和資產泡沫的問題。
舉例說,自2009年初新加坡元兌美元升值超過20%,但物業市場和香港一樣,出現過熱的情況,因此新加坡當局亦推出多項措施使市場降溫,包括對境外人士購買新加坡物業徵收額外的印花稅。
有很多研究發現,貨幣政策並非調控資產價格最有效的工具。原因是酌情利率政策很難只針對個別資產市場來發揮作用,而不會波及其他金融市場及整體經濟。若須針對資產市場過熱,利率可能須要大幅調升,對其他經濟層面可能造成過度負面的影響。針對物業及個別市場的政策,例如房屋供應、宏觀審慎及需求管理措施,會更有效處理物業市場過熱的問題。
■由於美元滙價及地位日趨衰落,港元與一籃子貨幣掛鈎是否較為合適?
首先,並沒有實證顯示美元必然會持續貶值。美元目前仍然是世界上主要儲備貨幣,亦是主要金融產品和貿易往來的計價和支付貨幣。 要知道國際主要交易和儲備貨幣(美元、歐羅、日圓、英鎊)之間的滙率是一個相對的關係,即使美國經濟增長仍然溫和,但歐羅區和英國等主要發達經濟體系亦面對類似問題,而情況可能比美國更差。雖然美元滙率短線波動在所難免,但不能斷定美元在中長線相對其他主要貨幣必然會持續貶值。
此外,與一籃子貨幣掛鈎的制度,仍然是掛鈎滙率制度(不論是固定或小幅調整滙率),香港同樣不會有獨立的貨幣政策。這個制度不及現行在貨幣發行局制度下與美元掛鈎的安排具透明度、簡單及具運作效率,而且公眾亦難於明白。
在一籃子貨幣掛鈎制度下,本港利率應為籃子內貨幣的相應利率的加權平均數。鑑於美元在香港的貿易份額中佔極大比重,因此在一籃子貨幣掛鈎制度下的港元利率應不會與聯滙制下的有很大差距。
假設港元與一籃子G3貨幣掛鈎,以貿易加權平均數計算,三個月港元銀行同業拆息在2012年的平均息率為0.44%,與同期的實際三個月港元銀行同業拆息的0.40%相若。轉為與一籃子貨幣掛鈎,不會令香港的貨幣狀況有任何重大變化,因此亦無助遏抑通脹或物業市場過熱。
■鑑於中港經濟日益融合,港元應否改與人民幣掛鈎?
中港經濟已經日益融合,內地有關當局也不斷努力推動人民幣作為國際貨幣,但考慮選擇人民幣作為港元的掛鈎貨幣言之尚早:
首先,人民幣現時仍未能完全自由和大量的兌換,尤其是內地資本賬並非完全開放,資金不能自由進出。此外,離岸人民幣的金融市場的廣度、深度和流動性亦未足夠讓外滙基金靈活持有人民幣資產以支持港元貨幣基礎。
另一個作為掛鈎貨幣的主要先決條件是兩地經濟的周期波動須較為同步。然而,儘管中港貿易持續增長,香港經濟的周期波動仍然在很大程度上受美國和其他發達經濟體所影響。
■人民幣兌美元處於升值的強勢,港元與人民幣掛鈎不是對香港有利嗎?
有意見指港元改為與人民幣掛鈎最有利香港,因為人民幣升值導致香港從內地進口價格上升,所以與人民幣掛鈎後可減輕香港進口通脹的壓力。也有意見認為香港和內地經濟已愈趨融合,經濟周期似乎也更為同步,因此適合貨幣掛鈎。
值得注意的是,內地作為一個新興市場經濟體,在經濟發展及人均收入追趕先進國家的過程中,滙率會傾向出現持續升值的趨勢。自2005年7月人民幣滙改以來,人民幣實質滙率已上升了將近40%,而名義滙率亦升值了接近30%。除了人民幣作為掛鈎貨幣的先決條件尚未存在之外,港元與一個持續升值的貨幣掛鈎,可能會因為競爭力以及兩地經濟結構差異而出現以下問題:
(一)在人民幣滙率升值的中期趨勢下,港元與人民幣掛鈎會令港元兌其他貨幣升值。因此,港元升值會削弱香港的貨物及服務出口競爭力,尤其是旅遊業和其他相關行業。由於香港的出口、物流、旅遊等行業佔香港經濟活動比重很大,不論在本地生產總值方面或就業方面都達到三成左右,影響不可小覷。而內地遊客對香港餐飲、零售、酒店住宿這三個行業的業務收益貢獻特別大。因此,這些僱有大量基層勞工的行業會首當其衝。
(二)雖然香港和內地經濟已愈趨融合,但是中港兩地經濟結構及生產力增長速度仍存在重大差異。因此在人民幣滙率升值的趨勢下,一旦港元與人民幣掛鈎,雙邊滙價不能調節,香港就可能承受本地價格(包括工資,物價及樓價等)下調的壓力,甚至要面對結構性通縮。要對抗薪酬下調唯一的方法就是增加勞動生產力來減低單位勞動成本(unit labour cost)。但香港經濟發展成熟程度較高,勞動生產力難以像內地一樣持續大幅增加。根據金管局估計,過去十年香港勞動生產力平均每年增長3-4%,遠低於內地接近10%的平均每年增速【註】。 因此本地工資將很可能承受下調壓力,進而拖累本地需求,打擊就業和實體經濟。
■即使維持聯滙制是香港最佳的政策選擇,是否有空間可以推出技術措施,進一步優化聯滙制,令制度更具彈性,例如重訂與美元掛鈎的水平或擴大兌換區間?
重訂與美元掛鈎的水平或擴大滙率波動區間,無助遏止資金流入或控制資產價格上升,此舉反而會引起市場猜測當局日後可能再擴大兌換區間或重訂掛鈎水平,嚴重削弱聯滙制的公信力及引致更多投機性資金流入或流出港元。
金管局因應亞洲金融危機於1998年9月推出七項技術性措施,以鞏固貨幣發行局制度,減低港元受到炒家操控的機會。此外,金管局又在2005年5月推出三項優化聯滙制運作的措施,以消除有關港元滙率在聯滙制下可轉強程度的不確定性。金管局因應市場環境的變化,不時檢視聯滙制度的運作,不排除在有需要時會推出措施,優化機制。但目前我們並不認為有這個需要。
■隨着離岸人民幣市場在香港發展,港元會否被邊緣化?
儘管香港正發展為全球最大的離岸人民幣中心,但這並不代表港元會被邊緣化。其實一種貨幣在本土是否被邊緣化,主要是取決於當地居民對該貨幣的信心,即是他們是否願意繼續使用它作為交易計價和儲蓄的工具。在這方面,香港市民對港元的信心仍然非常高。自2008年底以來,本港銀行體系的人民幣存款隨着人民幣業務的發展而大幅增長十二倍,至今年8月底的7095億人民幣,約佔整體存款的10%。但期內港元存款亦大幅增加至42050億港元,其佔銀行整體存款的比率,仍一直維持在過去二、三十年50%左右的水平,這反映港元存款並未因為人民幣存款增長而出現流失。事實上,香港作為國際金融中心,本港銀行體系的外幣存款一直約佔整體存款的一半,與其他國際金融中心如英國和新加坡的情況相若。
雖然在本港市場流通和使用人民幣隨着訪港內地旅客增多而有所上升,但以港元作為香港日常交易貨幣的需求有增無減。縱使現在電子轉賬和支付的使用愈來愈普遍,港元現鈔的流通量仍從2001年底的1080億港元,增長至2012年底的2920億港元,而其佔本地生產總值的比率,期內亦從8%上升至14%,這充分證明港元作為交易和支付貨幣完全沒有被邊緣化的跡象。
香港金融管理局
(全文共解答12項問題,本報節錄其中7項)
【註】勞動生產力是指每單位勞動力的實質產出,有多種計算方法。但由於中國內地並沒有實質工時的數據,為方便比較,這裡的勞動生產力以實質本地生產總值除以總就業人數來計算。中國內地數據來自經濟合作與發展組織(OECD),香港的數字則以統計處的數據計算得來。

2013年9月18日星期三

[信報]人民血汗錢補貼Tesla有因

http://www.hkej.com/template/dailynews/jsp/detail.jsp?dnews_id=3813&cat_id=4&title_id=628177
2013年9月18日

人民血汗錢補貼Tesla有因

萬眾期待的內地新能源車補貼方案,昨天正式出爐。一如所料,根據方案內容,比亞迪(1211)最為受惠。讓不少人意外的卻是,方案並無對海外品牌作出限制,意味消費者買一輛Tesla超跑,可享跟比亞迪同樣的補貼。
筆者本年初寫過〈比亞迪今年開車〉,斷言在當局刻意扶持下,比亞迪將進入電動車的收成期。年初至今,比亞迪累升逾五成,反映市場所見略同。
當局有必要扶持比亞迪,皆因電動車是未來最重要的工業之一。說「未來」,因為全球市場都還未成熟,但各國都很想捷足先登,爭做遊戲規則的制定者。而比亞迪,正是這個遊戲的「中國代表」。
昨天的方案,一如所料,傳統的混能車不獲列入,只有「純電動車」和「插電式混能車」可享補貼。在純電範疇,目前全球只得兩家以此掛帥、並已量產的車廠,即比亞迪和Tesla。至於插電式,全球不少車廠都有生產或試產。
孕育市場 爭做掌舵人
無論如何,比亞迪目前雄霸了中國的純電和插電式市場,肯定是方案的最大受惠者。例如其e6純電動車(即本港電動的士型號),目前標價30萬元(人民幣.下同),按方案可享6萬元補貼。其最新插電式超跑,型號為「秦」,估計售價18萬元,可享3.5萬元補貼。
但筆者認為,最有利的還不是上述直接補貼,而是方案裏面列明:「政府機關、公共機構等領域車輛採購,要向新能源汽車傾斜,比例不低於30%。」中國政府每年買車開支逾1200億元,今後最少三成要買新能源車,相當於400億元,等於比亞迪去年電動車銷售額的20倍以上。
最教人意外的在於未如以往「家電下鄉」或「電腦下鄉」般,限制海外品牌,反而列明:「不得設置或變相設置障礙,限制採購外地品牌車輛。」這既指江蘇省之於廣東省的「外地」,也包括美國等真正的「外地」。
Tesla北京旗艦店將於下季開業,屆時其Model S純電動車,估計售價60萬元起,按方案也可獲6萬元補貼。
當局用納稅人的血汗錢補貼Tesla,當然不是白白付出,因為中國並非只要扶持一兩家國產車廠,更要孕育全球首個電動車普及化的市場,掌握市場標準的主導權後,自然好處無盡。 

2013年7月21日星期日

2013年7月18日星期四

C optimisation tutorial

C optimisation tutorial

Introduction

This document has evolved over time and contains a number of the best ways to hand-optimise your C-code. Compilers are good, but they can't do everything, and here I hope to help you squeeze the best performance out of your code. This is not intended for beginners, but for more experienced programmers. 

Disclaimer

Depending on your particular hardware and compiler, some of these techniques may actually slow down your code. Do some timings with and without them, as modern compilers may well be able to do things better at a low level. Improving the overall algorithm used will often produce better results than localised code tweaking. This document was originally written as a set of personal notes for myself - do not consider it to be an authoritative paper on the subject of optimisation. I may have made mistakes! If you have anything to add to this, or just have some constructive criticism (flames ignored), please contact me at the address below.

Coding for speed

How to squeeze those last few T-states out of your C code. This only applies where you are more concerned with maximum speed and are less concerned with readability of code.
No error-checking is shown here as this article is only concerned with the fundamentals. By the time the application gets down to the low-level routines, you should have filtered out any bad data already.

Using array indices

If you wished to set a variable to a particular character, depending upon the value of something, you might do this :
switch ( queue ) {
case 0 :   letter = 'W';
   break;
case 1 :   letter = 'S';
   break;
case 2 :   letter = 'U';
   break;
}
or maybe
if ( queue == 0 )
  letter = 'W';
else if ( queue == 1 )
  letter = 'S';
else
  letter = 'U';
A neater ( and quicker ) method is to simply use the value as an index into a character array, eg.
static char *classes="WSU";

letter = classes[queue];

Aliases

Consider the following:
void func1( int *data )
{
    int i;

    for(i=0; i<10; i++)
    {
           somefunc2( *data, i);
    }
}
Even though "*data" may never change, the compiler does not know that somefunc2() did not alter it, and so the program must read it from memory each time it is used - it may be an alias for some other variable that is altered elsewhere. If you know it won't be altered, you could code it like this instead:
void func1( int *data )
{
    int i;
    int localdata;

    localdata = *data;
    for(i=0; i<10; i++)
    {
           somefunc2( localdata, i);
    }
}
This gives the compiler better opportunity for optimisation. 

Integers

Use unsigned ints instead of ints if you know the value will never be negative. Some processors can handle unsigned integer arithmetic considerably faster than signed ( this is also good practise, and helps make for self-documenting code). 
So the best declaration for an int variable in a tight loop would be
register unsigned int   var_name;
(although it is not guaranteed that the compiler will take any notice of "register", and "unsigned" may make no difference to the processor.) 
Remember, integer arithmetic is much faster than floating-point arithmetic, as it can be usually be done directly by the processor, rather than relying on external FPUs or floating point maths libraries. If you only need to be accurate to two decimal places (e.g. in a simple accounting package), scale everything up by 100, and convert it back to floating point as late as possible. 

Loop jamming

Never use two loops where one will suffice:
for(i=0; i<100; i++)
{
    stuff();
}

for(i=0; i<100; i++)
{
    morestuff();
}
It would be better to do:
for(i=0; i<100; i++)
{
    stuff();
    morestuff();
}
Note, however, that if you do a lot of work in the loop, it might not fit into your processor's instruction cache. In this case, two separate loops may actually be faster as each one can run completely in the cache. 

Loop Unrolling and Dynamic Loop Unrolling

This can make a BIG difference. 
It is well known that unrolling loops can produce considerable savings, e.g.
for(i=0; i<3; i++)
{
    something(i);
}
is less efficient than
something(0);
something(1);
something(2);
because the code has to check and increment the value of i each time round the loop. Compilers will often unroll simple loops like this, where a fixed number of iterations is involved, but something like
for(i=0;i<limit;i++){ ... }
is unlikely to be unrolled, as we don't know how many iterations there will be. It is, however, possible to unroll this sort of loop and take advantage of the speed savings that can be gained. A good example of this was given in the "Graphic Gems" series of books, as a way of speeding up the display of pixels in a scanline during graphics rendering, but can also be applied to any situation which involves the same operation being applied to a large amount of data. 
The following code (listing 1) is obviously much larger than a simple loop, but is much more efficient. The block-size of 8 was chosen just for demo purposes, as any suitable size will do - you just have to repeat the "loop-contents" the same amount. In this example, the loop-condition is tested once every 8 iterations, instead of on each one. If you know that you will working with arrays of a certain size, you could make the blocksize the same size as (or divisible into the size of) the array. I find 8 to be an adequate size though. I tried some performance tests using this technique on a Sun Sparcstation, and block-sizes of 8 and 16 worked fine, but when I went up to 32, it slowed right down again (again, I suspect this was to do with the size of the machines cache). 
I have used code similar to this in an image-processing application, to negate a large monochrome bitmap (of about 3000x2000 pixels), and it was significantly faster than using a simple for() type loop, as the processor was able to get on with the job of processing the data rather than incrementing counters and testing the loop conditions.

Listing 1

#include<stdio.h> 

#define BLOCKSIZE (8) 

void main(void)
{ 
int i = 0; 
int limit = 33;  /* could be anything */ 
int blocklimit; 

/* The limit may not be divisible by BLOCKSIZE, 
 * go as near as we can first, then tidy up.
 */ 
blocklimit = (limit / BLOCKSIZE) * BLOCKSIZE; 

/* unroll the loop in blocks of 8 */ 
while( i < blocklimit ) 
{ 
    printf("process(%d)\n", i); 
    printf("process(%d)\n", i+1); 
    printf("process(%d)\n", i+2); 
    printf("process(%d)\n", i+3); 
    printf("process(%d)\n", i+4); 
    printf("process(%d)\n", i+5); 
    printf("process(%d)\n", i+6); 
    printf("process(%d)\n", i+7); 

    /* update the counter */ 
    i += 8; 

} 

/* 
 * There may be some left to do.
 * This could be done as a simple for() loop, 
 * but a switch is faster (and more interesting) 
 */ 

if( i < limit ) 
{ 
    /* Jump into the case at the place that will allow
     * us to finish off the appropriate number of items. 
     */ 

    switch( limit - i ) 
    { 
        case 7 : printf("process(%d)\n", i); i++; 
        case 6 : printf("process(%d)\n", i); i++; 
        case 5 : printf("process(%d)\n", i); i++; 
        case 4 : printf("process(%d)\n", i); i++; 
        case 3 : printf("process(%d)\n", i); i++; 
        case 2 : printf("process(%d)\n", i); i++; 
        case 1 : printf("process(%d)\n", i); 
    }
} 

}
Another simple trick to use with loops is to count down, instead of up. Look at this code, which will go through the values of i=0 to i=9 :
for(i=0; i<10; i++)
{
  do stuff...
}
If the order in which the loop contents are executed does not matter, you can do this instead:
for( i=10; i--; )
which will step through i=9, down to i=0.It is important to use "i--" rather than "--i", otherwise the loop will terminate early. 

Faster for() loops

Simple but effective. 
Ordinarily, you would code a simple for() loop like this:
for( i=0;  i<10;  i++){ ... }
i loops through the values 0,1,2,3,4,5,6,7,8,9
If you don't care about the order of the loop counter, you can do this instead:
for( i=10; i--; ) { ... }
Using this code, i loops through the values 9,8,7,6,5,4,3,2,1,0, and the loop should be faster. 
This works because it is quicker to process "i--" as the test condition, which says "is i non-zero? If so, decrement it and continue.". 
For the original code, the processor has to calculate "subtract i from 10. Is the result non-zero? if so, increment i and continue.". In tight loops, this make a considerable difference.
The syntax is a little strange, put is perfectly legal. The third statement in the loop is optional (an infinite loop would be written as "for( ; ; )" ). The same effect could also be gained by coding:
for(i=10; i; i--){}
or (to expand it further)
for(i=10; i!=0; i--){}
The only things you have to be careful of are remembering that the loop stops at 0 (so if you wanted to loop from 50-80, this wouldn't work), and the loop counter goes backwards.It's easy to get caught out if your code relies on an ascending loop counter.


 

switch() instead of if...else...

For large decisions involving if...else...else..., like this:
if( val == 1)
    dostuff1();
else if (val == 2)
    dostuff2();
else if (val == 3)
    dostuff3();
it may be faster to use a switch:
switch( val )
{
    case 1: dostuff1(); break;

    case 2: dostuff2(); break;

    case 3: dostuff3(); break;
}
In the if() statement, if the last case is required, all the previous ones will be tested first. The switch lets us cut out this extra work. If you have to use a big if..else.. statement, test the most likely cases first. 

Pointers

Whenever possible, pass structures by reference ( ie. pass a pointer to the structure ), otherwise the whole darn thing will be copied onto the stack and passed, which will slow things down a tad (I've seen programs that pass structures several megabytes in size by value, when a simple pointer will do the same thing). 
Functions receiving pointers to structures as arguments should declare them as pointer to const if the function is not going to alter the contents of the structure, e.g.
void print_data( const bigstruct  *data_pointer)
{
    ...printf contents of structure...
}
This example informs the compiler that the function does not alter the contents (pointer to constant structure) of the external structure, and does not need to keep re-reading the contents each time they are accessed. It also ensures that the compiler will trap any accidental attempts by your code to write to the read-only structure. 

Early loop breaking

It is often not necessary to process the entirety of  a loop. For example, if you are searching an array for a particular item, break out of the loop as soon as you have got what you need. 
Example: 
This loop searches a list of 10000 numbers to see if there is a -99 in it.
found = FALSE;
for(i=0;i<10000;i++)
{
    if( list[i] == -99 )
    {
        found = TRUE;
    }
}
if( found ) printf("Yes, there is a -99. Hooray!\n");
This works well, but will process the entire array, no matter where the search item occurs in it.
A better way is to abort the search as soon as you've found the desired entry.
found = FALSE;
for(i=0; i<10000; i++)
{
    if( list[i] == -99 )
    {
        found = TRUE;
        break;
    }
}
if( found ) printf("Yes, there is a -99. Hooray!\n");
If the item is at, say position 23, the loop will stop there and then, and skip the remaining 9977 iterations.

Misc.

  • In general, savings can be made by trading off memory for speed. If you can cache any often used data rather than recalculating or reloading it, it will help. Examples of this would be sine/cosine tables, or tables of pseudo-random numbers (calculate 1000 once at the start, and just reuse them if you don't need truly random numbers).
  • Avoid using ++ and -- etc. within loop expressions, eg. while(n--){}, as this can sometimes be harder to optimise.
  • Minimize the use of global variables.
  • Declare anything within a file (external to functions) as static, unless it is intended to be global.
  • Use word-size variables if you can, as the machine can work with these better ( instead of char, short, double, bitfields etc. ).
  • Don't use recursion. Recursion can be very elegant and neat, but creates many more function calls which can become a large overhead.
  • Avoid the sqrt() square root function in loops - calculating square roots is very CPU intensive.
  • Single dimension arrays are faster than multi-dimensioned arrays.
  • Compilers can often optimise a whole file - avoid splitting off closely related functions into separate files, the compiler will do better if can see both of them together (it might be able to inline the code, for example).
  • Single precision maths may be faster than double precision - there is often a compiler switch for this.
  • Floating point multiplication is often faster than division - use val * 0.5 instead of val / 2.0.
  • Addition is quicker than multiplication - use val + val + val instead of val * 3
  • puts() is quicker than printf(), although less flexible.
  • Use #defined macros instead of commonly used tiny functions - sometimes the bulk of CPU usage can be tracked down to a small external function being called thousands of times in a tight loop. Replacing it with a macro to perform the same job will remove the overhead of all those function calls, and allow the compiler to be more aggressive in it's optimisation..
  • Binary/unformatted file access is faster than formatted access, as the machine does not have to convert between human-readable ASCII and machine-readable binary. If you don't actually need to read the data in a file yourself, consider making it a binary file.
  • If your library supports the mallopt() function (for controlling malloc), use it. The MAXFAST setting can make significant improvements to code that does a lot of malloc work.If a particular structure is created/destroyed many times a second, try setting the mallopt options to work best with that size.
  • Last but definitely not least - turn compiler optimisation on! Seems obvious, but is often forgotten in that last minute rush to get the product out on time. The compiler will be able to optimise at a much lower level than can be done in the source code, and perform optimisations specific to the target processor.


Last updated July 1998
If you find any of this helps to dramatically increase the performance of your software, please let me know. 

Now Available - Vatican Approved Debugger

Debug your code by faith alone 

Check out the Amiga Programmers Web Site 

中文:http://just-study.blogbus.com/logs/37238127.html

2013年7月2日星期二

BASH 的基本语法

BASH 的基本语法 source
最简单的例子 —— Hello World!
关于输入、输出和错误输出
BASH 中对变量的规定(与 C 语言的异同)
BASH 中的基本流程控制语法
函数的使用
2.1     最简单的例子 —— Hello World!
几乎所有的讲解编程的书给读者的第一个例子都是 Hello World 程序,那么我们今天也就从这个例子出发,来逐步了解 BASH。
用 vi 编辑器编辑一个 hello 文件如下:

#!/bin/bash
# This is a very simple example
echo Hello World
这样最简单的一个 BASH 程序就编写完了。这里有几个问题需要说明一下:
一,第一行的 #! 是什么意思
二,第一行的 /bin/bash 又是什么意思
三,第二行是注释吗
四,echo 语句
五,如何执行该程序
#! 是说明 hello 这个文件的类型的,有点类似于 Windows 系统下用不同文件后缀来表示不同文件类型的意思(但不相同)。Linux 系统根据 "#!" 及该字串后面的信息确定该文件的类型,关于这一问题同学们回去以后可以通过 "man magic"命令 及 /usr/share/magic 文件来了解这方面的更多内容。在 BASH 中 第一行的 "#!" 及后面的 "/bin/bash" 就表明该文件是一个 BASH 程序,需要由 /bin 目录下的 bash 程序来解释执行。BASH 这个程序一般是存放在 /bin 目录下,如果你的 Linux 系统比较特别,bash 也有可能被存放在 /sbin 、/usr/local/bin 、/usr/bin 、/usr/sbin 或 /usr/local/sbin 这样的目录下;如果还找不到,你可以用 "locate bash" "find / -name bash 2> /dev/null" 或 "whereis bash" 这三个命令找出 bash 所在的位置;如果仍然找不到,那你可能需要自己动手安装一个 BASH 软件包了。
第二行的 "# This is a ..." 就是 BASH 程序的注释,在 BASH 程序中从“#”号(注意:后面紧接着是“!”号的除外)开始到行尾的多有部分均被看作是程序的注释。的三行的 echo 语句的功能是把 echo 后面的字符串输出到标准输出中去。由于 echo 后跟的是 "Hello World" 这个字符串,因此 "Hello World"这个字串就被显示在控制台终端的屏幕上了。需要注意的是 BASH 中的绝大多数语句结尾处都没有分号。
如何执行该程序呢?有两种方法:一种是显式制定 BASH 去执行:
$ bash hello 或
$ sh hello (这里 sh 是指向 bash 的一个链接,“lrwxrwxrwx 1 root root 4 Aug 20 05:41 /bin/sh -> bash”)
或者可以先将 hello 文件改为可以执行的文件,然后直接运行它,此时由于 hello 文件第一行的 "#! /bin/bash" 的作用,系统会自动用/bin/bash 程序去解释执行 hello 文件的:
$ chmod u+x hello
$ ./hello
此处没有直接 “$ hello”是因为当前目录不是当前用户可执行文件的默认目录,而将当前目录“.”设为默认目录是一个不安全的设置。
需要注意的是,BASH 程序被执行后,实际上 Linux 系统是另外开设了一个进程来运行的。

2.2     关于输入、输出和错误输出
在字符终端环境中,标准输入/标准输出的概念很好理解。输入即指对一个应用程序 或命令的输入,无论是从键盘输入还是从别的文件输入;输出即指应用程序或命令产生的一些信息;与 Windows 系统下不同的是,Linux 系统下还有一个标准错误输出的概念,这个概念主要是为程序调试和系统维护目的而设置的,错误输出于标准输出分开可以让一些高级的错误信息不干扰正常的输出 信息,从而方便一般用户的使用。
在 Linux 系统中:标准输入(stdin)默认为键盘输入;标准输出(stdout)默认为屏幕输出;标准错误输出(stderr)默认也是输出到屏幕(上面的 std 表示 standard)。在 BASH 中使用这些概念时一般将标准输出表示为 1,将标准错误输出表示为 2。下面我们举例来说明如何使用他们,特别是标准输出和标准错误输出。
输入、输出及标准错误输出主要用于 I/O 的重定向,就是说需要改变他们的默认设置。先看这个例子:
$ ls > ls_result
$ ls -l >> ls_result
上面这两个命令分别将 ls 命令的结果输出重定向到 ls_result 文件中和追加到 ls_result 文件中,而不是输出到屏幕上。">"就是输出(标准输出和标准错误输出)重定向的代表符号,连续两个 ">" 符号,即 ">>" 则表示不清除原来的而追加输出。下面再来看一个稍微复杂的例子:
$ find /home -name lost* 2> err_result
这个命令在 ">" 符号之前多了一个 "2","2>" 表示将标准错误输出重定向。由于 /home 目录下有些目录由于权限限制不能访问,因此会产生一些标准错误输出被存放在 err_result 文件中。大家可以设想一下 find /home -name lost* 2>>err_result 命令会产生什么结果?
如果直接执行 find /home -name lost* > all_result ,其结果是只有标准输出被存入 all_result 文件中,要想让标准错误输出和标准输入一样都被存入到文件中,那该怎么办呢?看下面这个例子:
$ find /home -name lost* > all_result 2>& 1
上面这个例子中将首先将标准错误输出也重定向到标准输出中,再将标准输出重定向到 all_result 这个文件中。这样我们就可以将所有的输出都存储到文件中了。为实现上述功能,还有一种简便的写法如下:
$ find /home -name lost* >& all_result

如果那些出错信息并不重要,下面这个命令可以让你避开众多无用出错信息的干扰:
$ find /home -name lost* 2> /dev/null
同学们回去后还可以再试验一下如下几种重定向方式,看看会出什么结果,为什么?
$ find /home -name lost* > all_result 1>& 2
$ find /home -name lost* 2> all_result 1>& 2
$ find /home -name lost* 2>& 1 > all_result
另外一个非常有用的重定向操作符是 "-",请看下面这个例子:
$ (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xvfp -)
该命令表示把 /source/directory 目录下的所有文件通过压缩和解压,快速的全部移动到 /dest/directory 目录下去,这个命令在 /source/directory 和 /dest/directory 不处在同一个文件系统下时将显示出特别的优势。
下面还几种不常见的用法:
n<&- 表示将 n 号输入关闭
<&- 表示关闭标准输入(键盘)
n>&- 表示将 n 号输出关闭
>&- 表示将标准输出关闭
2.3     BASH 中对变量的规定(与 C 语言的异同)
好了下面我们进入正题,先看看 BASH 中的变量是如何定义和使用的。对于熟悉 C 语言的程序员,我们将解释 BASH 中的定义和用法与 C 语言中有何不同。
2.3.1. BASH 中的变量介绍
我们先来从整体上把握一下 BASH 中变量的用法,然后再去分析 BASH 中变量使用与 C 语言中的不同。BASH 中的变量都是不能含有保留字,不能含有 "-" 等保留字符,也不能含有空格。
2.3.1.1 简单变量
在 BASH 中变量定义是不需要的,没有 "int i" 这样的定义过程。如果想用一个变量,只要他没有在前面被定义过,就直接可以用,当然你使用该变量的第一条语句应该是对他赋初值了,如果你不赋初值也没关 系,只不过该变量是空( 注意:是 NULL,不是 0 )。不给变量赋初值虽然语法上不反对,但不是一个好的编程习惯。好了我们看看下面的例子:
首先用 vi 编辑下面这个文件 hello2:
#!/bin/bash
# give the initialize value to STR
STR="Hello World"
echo $STR

在上面这个程序中我们需要注意下面几点:
一,变量赋值时,'='左右两边都不能有空格;
二,BASH 中的语句结尾不需要分号(";");
三,除了在变量赋值和在FOR循环语句头中,BASH 中的变量使用必须在变量前加"$"符号,同学们可以将上面程序中第三行改为 "echo STR" 再试试,看看会出什么结果。==>output: STR
四,由于 BASH 程序是在一个新的进程中运行的,所以该程序中的变量定义和赋值不会改变其他进程或原始 Shell 中同名变量的值,也不会影响他们的运行。
更细致的文档甚至提到以但引号括起来的变量将不被 BASH 解释为变量,如 '$STR' ,而被看成为纯粹的字符串。而且更为标准的变量引用方式是 ${STR} 这样的,$STR 自不过是对 ${STR} 的一种简化。在复杂情况下(即有可能产生歧义的地方)最好用带 {} 的表示方式。
BASH 中的变量既然不需要定义,也就没有类型一说,一个变量即可以被定义为一个字符串,也可以被再定义为整数。如果对该变量进行整数运算,他就被解释为整数;如果对他进行字符串操作,他就被看作为一个字符串。请看下面的例子:
#!/bin/bash
x=1999
let "x = $x + 1"
echo $x
x="olympic'"$x
echo $x
关于整数变量计算,有如下几种:" + - * / % ",他们的意思和字面意思相同。整数运算一般通过 let 和 expr 这两个指令来实现,如对变量 x 加 1 可以写作:let "x = $x + 1" 或者 x=`expr $x + 1`
在比较操作上,整数变量和字符串变量各不相同,详见下表:
对应的操作
整数操作
字符串操作
相同
-eq
=
不同
-ne
!=
大于
-gt
>
小于
-lt
<
大于或等于
-ge

小于或等于
-le

为空

-z
不为空

-n

比如:
比较字符串 a 和 b 是否相等就写作:if [ $a = $b ]
判断字符串 a 是否为空就写作: if [ -z $a ]
判断整数变量 a 是否大于 b 就写作:if [ $a -gt $b ]
更细致的文档推荐在字符串比较时尽量不要使用 -n ,而用 ! -z 来代替。(其中符号 "!" 表示求反操作)
BASH 中的变量除了用于对 整数 和 字符串 进行操作以外,另一个作用是作为文件变量。BASH 是 Linux 操作系统的 Shell,因此系统的文件必然是 BASH 需要操作的重要对象,如 if [ -x /root ] 可以用于判断 /root 目录是否可以被当前用户进入。下表列出了 BASH 中用于判断文件属性的操作符:
运算符
含义( 满足下面要求时返回 TRUE )
-e file
文件 file 已经存在
-f file
文件 file 是普通文件
-s file
文件 file 大小不为零
-d file
文件 file 是一个目录
-r file
文件 file 对当前用户可以读取
-w file
文件 file 对当前用户可以写入
-x file
文件 file 对当前用户可以执行
-g file
文件 file 的 GID 标志被设置
-u file
文件 file 的 UID 标志被设置
-O file
文件 file 是属于当前用户的
-G file
文件 file 的组 ID 和当前用户相同
file1 -nt file2
文件 file1 比 file2 更新
file1 -ot file2
文件 file1 比 file2 更老

注意:上表中的 file 及 file1、file2 都是指某个文件或目录的路径。
2.3.1.1. 关于局部变量
在 BASH 程序中如果一个变量被使用了,那么直到该程序的结尾,该变量都一直有效。为了使得某个变量存在于一个局部程序块中,就引入了局部变量的概念。BASH 中,在变量首次被赋初值时加上 local 关键字就可以声明一个局部变量,如下面这个例子:
#!/bin/bash
HELLO=Hello
function hello {
local HELLO=World
echo $HELLO
}
echo $HELLO
hello
echo $HELLO
该程序的执行结果是:
Hello
World
Hello
这个执行结果表明全局变量 $HELLO 的值在执行函数 hello 时并没有被改变。也就是说局部变量 $HELLO 的影响只存在于函数那个程序块中。
2.3.2. BASH 中的变量与 C 语言中变量的区别
这里我们为原来不熟悉 BASH 编程,但是非常熟悉 C 语言的程序员总结一下在 BASH 环境中使用变量需要注意的问题。
1,BASH 中的变量在引用时都需要在变量前加上 "$" 符号( 第一次赋值及在For循环的头部不用加 "$"符号 );
2,BASH 中没有浮点运算,因此也就没有浮点类型的变量可用;
3,BASH 中的整形变量的比较符号与 C 语言中完全不同,而且整形变量的算术运算也需要经过 let 或 expr 语句来处理;
2.4     BASH 中的基本流程控制语法
BASH 中几乎含有 C 语言中常用的所有控制结构,如条件分支、循环等,下面逐一介绍。
2.4.1 if...then...else
if 语句用于判断和分支,其语法规则和 C 语言的 if 非常相似。其几种基本结构为:
if [ expression ]
then
statments
fi
或者
if [ expression ]
then
statments
else
statments
fi
或者
if [ expression ]
then
statments
else if [ expression ]
then
statments
else
statments
fi
或者
if [ expression ]
then
statments
elif [ expression ]
then
statments
else
statments
fi
值得说明的是如果你将 if 和 then 简洁的写在一行里面,就必须在 then 前面加上分号,如:if [ expression ]; then ... 。下面这个例子说明了如何使用 if 条件判断语句:
#!/bin/bash

if [ $1 -gt 90 ]
then
echo "Good, $1"
elif [ $1 -gt 70 ]
then
echo "OK, $1"
else
echo "Bad, $1"
fi

exit 0
上面例子中的 $1 是指命令行的第一个参数,这个会在后面的“BASH 中的特殊保留字”中讲解。
2.4.2 for
for 循环结构与 C 语言中有所不同,在 BASH 中 for 循环的基本结构是:
for $var in

do
statments
done
其中 $var 是循环控制变量,
是 $var 需要遍历的一个集合,do/done 对包含了循环体,相当于 C 语言中的一对大括号。另外如果do 和 for 被写在同一行,必须在 do 前面加上 ";"。如: for $var in ; do 。下面是一个运用 for 进行循环的例子:
#!/bin/bash

for day in Sun Mon Tue Wed Thu Fri Sat
do
echo $day
done

# 如果列表被包含在一对双引号中,则被认为是一个元素
for day in "Sun Mon Tue Wed Thu Fri Sat"
do
echo $day
done

exit 0
注意上面的例子中,在 for 所在那行的变量 day 是没有加 "$" 符号的,而在循环体内,echo 所在行变量 $day 是必须加上 "$" 符号的。另外如果写成 for day 而没有后面的 in
部分,则 day 将取遍命令行的所有参数。如这个程序:
#!/bin/bash

for param
do
echo $param
done

exit 0
上面这个程序将列出所有命令行参数。for 循环结构的循环体被包含在 do/done 对中,这也是后面的 while、until 循环所具有的特点。
2.4.3 while
while 循环的基本结构是:
while [ condition ]
do
statments
done
这个结构请大家自己编写一个例子来验证。
2.4.4 until
until 循环的基本结构是:
until [ condition is TRUE ]
do
statments
done
这个结构也请大家自己编写一个例子来验证。
2.4.5 case
BASH 中的 case 结构与 C 语言中的 switch 语句的功能比较类似,可以用于进行多项分支控制。其基本结构是:
case "$var" in
condition1 )
statments1;;
condition2 )
statments2;;
...
* )
default statments;;
esac
下面这个程序是运用 case 结构进行分支执行的例子:
#!/bin/bash

echo "Hit a key, then hit return."
read Keypress

case "$Keypress" in
[a-z] ) echo "Lowercase letter";;
[A-Z] ) echo "Uppercase letter";;
[0-9] ) echo "Digit";;
* ) echo "Punctuation, whitespace, or other";;
esac

exit 0
上面例子中的第四行 "read Keypress" 一句中的 read 语句表示从键盘上读取输入。这个命令将在本讲义的 BASH 的其他高级问题中讲解。
2.4.6 break/continue
熟悉 C 语言编程的都很熟悉 break 语句和 continue 语句。BASH 中同样有这两条语句,而且作用和用法也和 C 语言中相同,break 语句可以让程序流程从当前循环体中完全跳出,而 continue 语句可以跳过当次循环的剩余部分并直接进入下一次循环。
2.5     函数的使用
BASH 是一个相对简单的脚本语言,不过为了方便结构化的设计,BASH 中也提供了函数定义的功能。BASH 中的函数定义很简单,只要向下面这样写就可以了:
function my_funcname {
code block
}
或者
my_funcname() {
code block
}
上面的第二种写法更接近于 C 语言中的写法。BASH 中要求函数的定义必须在函数使用之前,这是和 C 语言用头文件说明函数方法的不同。
更进一步的问题是如何给函数传递参数和获得返回值。BASH 中函数参数的定义并不需要在函数定义处就制定,而只需要在函数被调用时用 BASH 的保留变量 $1 $2 ... 来引用就可以了;BASH 的返回值可以用 return 语句来指定返回一个特定的整数,如果没有 return 语句显式的返回一个返回值,则返回值就是该函数最后一条语句执行的结果(一般为 0,如果执行失败返回错误码)。函数的返回值在调用该函数的程序体中通过 $? 保留字来获得。下面我们就来看一个用函数来计算整数平方的例子:
#!/bin/bash

square() {
let "res = $1 * $1"
return $res
}

square $1
result=$?
echo $result

exit 0

BASH 中的特殊保留字
保留变量
随机数
运算符
变量的特殊操作
3.1     保留变量
BASH 中有一些保留变量,下面列出了一些:

$IFS  这个变量中保存了用于分割输入参数的分割字符,默认识空格。
$HOME  这个变量中存储了当前用户的根目录路径。
$PATH  这个变量中存储了当前 Shell 的默认路径字符串。
$PS1  表示第一个系统提示符。
$PS2  表示的二个系统提示符。
$PWD  表示当前工作路径。
$EDITOR 表示系统的默认编辑器名称。
$BASH  表示当前 Shell 的路径字符串。
$0, $1, $2, ...
表示系统传给脚本程序或脚本程序传给函数的第0个、第一个、第二个等参数。
$#   表示脚本程序的命令参数个数或函数的参数个数。
$$   表示该脚本程序的进程号,常用于生成文件名唯一的临时文件。
$?   表示脚本程序或函数的返回状态值,正常为 0,否则为非零的错误号。
$*   表示所有的脚本参数或函数参数。
$@   和 $* 涵义相似,但是比 $* 更安全。
$!   表示最近一个在后台运行的进程的进程号。

3.2    随机数
随机数是经常要用到的,BASH 中也提供了这个功能,请看下面这个程序:
#!/bin/bash

# Prints different random integer from 1 to 65536

a=$RANDOM
echo $a

exit 0
这个程序可以在每次执行的时候随机的打印出一个大小在 1 到 65536 之间的整数。
3.3     运算符
算术运算符
+ - * / % 表示加减乘除和取余运算
+= -= *= /= 同 C 语言中的含义
位操作符
<< <<= >> >>= 表示位左右移一位操作
& &= | |= 表示按位与、位或操作
~ ! 表示非操作
^ ^= 表示异或操作
关系运算符
< > <= >= == != 表示大于、小于、大于等于、小于等于、等于、不等于操作
&& || 逻辑与、逻辑或操作
3.4     变量的特殊操作
BASH 中还有一些对变量的简洁、快速的操作,大家还记得 "${var}" 和 "$var" 同样是对变量的引用吧,对 ${var} 进行一些变化就可以产生一些新功能:
${var-default} 表示如果变量 $var 还没有设置,则保持 $var 没有设置的状态,并返回后面的默认值 default。
${var=default} 表示如果变量 $var 还没有设置,则取后面的默认值 default。
${var+otherwise} 表示如果变量 $var 已经设置,则返回 otherwise 的值,否则返回空( null )。
${var?err_msg} 表示如果变量 $var 已经设置,则返回该变量的值,否则将后面的 err_msg 输出到标准错误输出上。
请同学们自己尝试下面的例子:
#!/bin/bash

echo ${var?There is an error}

exit 0
还有下面一些用法,这些用法主要用于从文件路径字符串中提取有用信息:
${var#pattern}, ${var##pattern} 用于从变量 $var 中剥去最短(最长)的和 pattern 相匹配的最左侧的串。
${var%pattern}, ${var%%pattern} 用于从变量 $var 中剥去最短(最长)的和 pattern 相匹配的最右侧的串。
另外 BASH 2 中还加入下面一些操作:
${var:pos} 表示去掉变量 $var 中前 pos 个字符。
${var:pos:len} 表示变量 $var 中去掉前 pos 个字符后的剩余字符串的前 len 个字符。
${var/pattern/replacement} 表示将变量 $var 中第一个出现的 pattern 模式替换为 replacement 字符串。
${var//pattern/replacement} 表示将变量 $var 中出现的所有 pattern 模式全部都替换为 replacment 字符串。

BASH 中的其他高级问题
BASH 中对返回值的处理
用 BASH 设计简单用户界面
在 BASH 中读取用户输入
一些特殊的惯用法
BASH 程序的调试
关于 BASH2
4.1     BASH 中对返回值的处理
无论是在 Shell 中对 BASH 脚本返回值的处理,还是在脚本中对函数返回值的处理,都是通过 "$?" 系统变量来获得。BASH 要求返回值必须为一个整数,不能用 return 语句返回字符串变量。

4.2     用 BASH 设计简单用户界面
BASH 中提供了一个小的语句格式,可以让程序快速的设计出一个字符界面的用户交互选择的菜单,该功能就是由 select 语句来实现的,select 语句的语法为:
select var in

do
statments use $var
done
上面的语法结构在执行后,BASH 会将
中的所有项加上数字列在屏幕上等待用户选择,在用户作出选择后,变量 $var 中就包含了那个被选中的字符串,然后就可以对该变量进行需要的操作了。我们可以从下面的例子中更直观的来理解这个功能:
#!/bin/bash

OPTIONS="Hello Quit"
select opt in $OPTIONS; do
if [ "$opt" = "Quit" ]; then
echo done
exit
elif [ "$opt" = "Hello" ]; then
echo Hello World
else
clear
echo bad option
fi
done

exit 0
大家可以试着执行上面的程序,看看是什么执行结果。
4.3     在 BASH 中读取用户输入
BASH 中通过 read 函数来实现读取用户输入的功能,如下面这段程序:
#!/bin/bash

echo Please enter your name
read NAME
echo "Hi! $NAME !"

exit 0
上面这个脚本读取用户的输入,并回显在屏幕上。
另外 BASH 中还提供另外一种称为 here documents 的结构????,可以将用户需要通过键盘输入的字符串改为从程序体中直接读入,如密码。下面的小程序演示了这个功能:
#!/bin/bash

passwd="aka@tsinghua"
ftp -n localhost <<FTPFTP
user anonymous $passwd
binary
bye
FTPFTP

exit 0
这个程序在用户需要通过键盘敲入一些字符时,通过程序内部的动作来模拟键盘输入。请注意 here documents 的基本结构为:
command <<SOMESPECIALSTRING
statments
...
SOMESPECIALSTRING
这里要求在需要键盘输入的命令后,直接加上 <<符号,然后跟上一个特别的字符串,在该串后按顺序输入本来应该由键盘输入的所有字符,在所有需要输入的字符都结束后,重复一遍前面 <<符号后的“特别的字符串”即表示该输入到此结束。
4.4 一些特殊的惯用法
在 BASH 中 () 一对括号一般被用于求取括号中表达式的值或命令的执行结果,如:(a=hello; echo $a) ,其作用相当于 `...` 。
: 有两个含义,一是表示空语句,有点类似于 C 语言中的单个 ";" 。表示该行是一个空命令,如果被用在 while/until 的头结构中,则表示值 0,会使循环一直进行下去,如下例:
while :
do
operation-1
operation-2
...
operation-n
done
另外 : 还可以用于求取后面变量的值,比如:
#!/bin/bash

: ${HOSTNAME?} {USER?} {MAIL?}
echo $HOSTNAME
echo $USER
echo $MAIL

exit 0
在 BASH 中 export 命令用于将系统变量输出到外层的 Shell 中了。
4.5 BASH 程序的调试
用 bash -x bash-script 命令,可以查看一个出错的 BASH 脚本到底错在什么地方,可以帮助程序员找出脚本中的错误。
另外用 trap 语句可以在 BASH 脚本出错退出时打印出一些变量的值,以供程序员检查。trap 语句必须作为继 "#!/bin/bash" 后的第一句非注释代码,一般 trap 命令被写作: trap 'message $checkvar1 $checkvar2' EXIT 。
4.6 关于 BASH2
使用 bash -version 命令可以看出当前你正在使用的 BASH 是什么版本,一般版本号为1.14或其他版本。而现在机器上一般还安装了一个版本号为 2.0 的 BASH 。该 BASH 也在 /bin 目录下。BASH2 提供了一些新功能,有兴趣的同叙可以自己去看相关资料,或直接 man bash2 即可。

2013年6月6日星期四

當前的置業策略(2013/03/13)

當前的置業策略(2013/03/13) 
有發展商劈價17%賣一手盤,據稱二手市場一些業主開始放棄「大紅樓盤高高掛」,願意貼市價掛盤,甚至擺出「萬事有商量,請開個價」的姿態。對於一些心大心細了一輪的買家,又重燃了入市的期望。
如以過去數次的調整經驗,樓價略為調整已是入市機會,其後樓價會繼續上升,進入一浪高於一浪,以下是數據分析:
月份中原指數升幅跌幅
2003/0831.7776%
2005/0656.07-8%
2006/0951.8643%
2008/0373.98-23%
2008/1256.7178%
2011/06100.72-7%
2012/0194.1630%
2013/03121.95
比如金融海嘯時曾下跌23%,其後錄得78%的升幅;而2011年下半年因政府多翻出招而下跌7%,至今樓價已上升了30%。不過換一個角度,大跌市的進程又如何呢?
月份中原指數升幅跌幅
1997/10102.93-56%
1998/1045.7125%
1999/0457.23-44%
2003/0831.77
筆者曾經在1998年官鱷大戰時賣了物業,當時指數大約53點,然後大市升到57.23點,即反彈了7%;最終大市下跌到31.77點,若果當時沒有賣樓,總跌幅是40%,即接貨者在最低位時負資產10%(以七成按揭計算)。
筆者翻查紀錄,當時接貨者持有至今都沒有賣過,以現時121.95點計,即是以買入價計上升了1.3倍!如果筆者沒有在2001年911事件後入市(指數大約40點),更要交十年租金,從機會成本看是輸得太多了!從這個事例筆者得出幾點教訓:
1. 買賣物業,或者租置選擇,一定要順從大方向,即是股市中的所謂牛熊市:在一浪高於一浪的牛市中,任何調整都是入市時機;在一浪低於一浪的熊市中,任何反彈都是出貨時機
2. 如何判斷牛熊市:如前文所述,短期市況由需求決定,長期市況由供應決定,因為需求是很有彈性的,一個消息或者政策都可以改變;但是供應是死翹翹的,供應過剩時,孫九招都要幾年至見效,供應不足時,像現在政府發晒矛,中藥院都要建豪宅都不能變出供應來
4. 扭轉樓市方向的,一定是長期供應,2002年的孫九招,要2004年才有明顯效用;2011年開始大量推地(見前文),由賣地到施工到落成要4-5年(其中由熟地到動工起碼要1-2年,由施工到落成要3年),所以筆者說2015年供應就會轉勢
5. 買了物業,要有長期持有的打算,尤其是政府的各種稅項,無論是何目的,最終的結果都是迫人減少交易,長期持有。沒有長期持有的意願和實力,還是租樓吧!
總結而言,若果是有實力持有三年以上(直到SSD失效),可以考慮在未來的調整入市,由2013-2015年應該仍然是牛市,再遠一點筆者看不到。 已經買了物業,自用或沒有急切財務需要的話,繼續持有享用相對低息或者是較佳選擇。如果想高位賣樓,在重重稅項之下,即使調整達30%,也是無所得著,所 以賣了樓的話,等下一浪吧!
以上分析並不涉及任何投資繳約或建議,買賣物業一定考慮個人情況,敬請量力而為。

2013年1月24日星期四

Compile gcc-4.1.2 on Ubuntu 12.04 64bit


Compile gcc-4.1.2 on Ubuntu 12.04 64bit

ftp://ftp.gnu.org/gnu/gcc/gcc-4.1.2/

Create a folder where to build the gcc version

mkdir ~/gcc412

Extract the downloaded gcc release to that folder

tar -C ~/gcc412/ -xzvf /path/to/the/file/gcc-4.1.2.tar.gz

Make a build folder:

mkdir ~/gcc412/gcc-build/

At this stage we should be ready to build but first we need to be sure that we've got all the dependencies needed to compile. We need the linux-headers gcc-multilib, zlib1g, zlib1g-dev, zlibc

sudo apt-get install linux-headers-$(uname -r) gcc-multilib zlib1g zlib1g-dev zlibc

Then we need also to fix some file in the gcc folder.

First of all you need to edit the file ~/gcc412/gcc-4.1.2/gcc/config/i386/t-linux64.

At line 9 you should find:
MULTILIB_OSDIRNAMES = ../lib64 ../lib

You need to modify it as follows:
MULTILIB_OSDIRNAMES = ../lib64 ../lib32

Open the file ~/gcc412/gcc-4.1.2/libstdc++-v3/configure and at line 8284 replace:
sed -e 's/GNU ld version \([0-9.][0-9.]*\).*/\1/'`

with:

sed -e 's/GNU ld (GNU Binutils for Ubuntu) \([0-9.][0-9.]*\).*/\1/'`

Last thing to do is to link some library otherwise the compiler won't find it.
cd /usr/lib
sudo ln -s x86_64-linux-gnu/crt1.o crt1.o
sudo ln -s x86_64-linux-gnu/crti.o crti.o
sudo ln -s x86_64-linux-gnu/crtn.o crtn.o
At this point we are ready to compile gcc.
Go in the build folder:
cd ~/gcc412/gcc-build

run the configure as autodesk suggests:
../configure --prefix=/opt/gcc412 --program-suffix=412 --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --disable-libunwind-exceptions --enable-__cxa_atexit --enable-languages=c,c++

and then compile it:
make -j 2 bootstrap MAKEINFO=makeinfo

As soon as the compiling process ends without throwing errors you will be able to run:
sudo make install

Setup remote debug gdb/gdbserver



cd /usr/local
mkdir arm-gdb

#download and build gdb for host "http://ftp.gnu.org/gnu/gdb/"
cd gdb-6.7
./configure --target=arm-linux-uclibc --prefix=/usr/local/arm-gdb --disable-werror
make
make install

#build gdbserver for target
cd ./gdb/gdbserver

#before building the gdbserver for target, the target toolchain should be ready first
./configure --target=arm-linux-uclibc --host=arm-linux-uclibc --prefix=/usr/local/arm-gdb/gdbserver
export PATH=$PATH:/root/workspace/skyhawk_trunk/build_arm/staging_dir/bin
make CC=arm-linux-uclibc-gcc
make install

#if using uclibc and need debug multi-thread program, make sure the PTHREADS_DEBUG_SUPPORT is enabled when building the library

Using Eclipse Juno Service Release 1 (Setting for debug with gdb/gdbserver)
Debug Configurations > C/C++ Application > change to GDB(DSF) Remote System Process Launcher>
Main (Tab):
  • input the execute file which run on target
Debugger (Tab):
  • select the custom build gdb debugger
  • Force thread list update on suspend (turn on for showing source when break inside thread)
  • .gdbinit (in project root)
    • set solib-absolute-prefix "paths of the .so that used in the project" (path1:path2)
    • set solib-search-path "paths of the .so that used in the project" (path1:path2)
    • handle SIG32 pass noprint nostop
    • set can-use-hw-watchpoints 0
  • Shared Libraries: input the paths of .so that used in the project (search from first line)
  • Connection: set the ip and port of the target which gdbserver is running at
Source(Tab):
  • input the path of the source file, gdb search from the first line

#Debugging steps
cross compile the program for target (disable strip if it exist in makefile)

copy all updated execute and .so file to target

$./gdbserver ip:port execute  (on target)

then start Debug from eclipse

problem not solved yet:
  • Cannot 'step into' the function inside a .so, but it can pause at the breakpoint preset in the .so function, if compiled the execute with .a , 'step into' is ok
  • if set breakpoint inside a function of .so, need to set again in every session of debug

Reference:
http://crasseux.com/books/ctutorial/Building-a-library.html

http://blog.csdn.net/hlchou/article/details/7425492
http://www.study-area.org/cyril/opentools/opentools/x1265.html


Some useful commands:
arm-linux-uclibc-ar -t libmylib.a      -list out the functions name inside the static library
nm --demangle libmylib.a/libmylib.so      -list out the functions name inside the static/shared library

2013年1月20日星期日

TFTP server for Ubuntu 12.04


TFTP server for Ubuntu 12.04 source

用apt-get直接裝TFTP server套件。

    sudo apt-get install tftpd-hpa

Default options放在 /etc/default/tftp-hpa

# /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/var/lib/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"

TFTP_DIRECTORY 是TFTP的檔案存放目錄.,我是將它改成rw for all,不知有沒有甚麼副作用?

    sudo chmod a+rw /var/lib/tftpboot

在Ubuntu上面直接裝的TFTP server套件不會在開機時執行,精確一點說應該是開機時跑了卻沒有起來。這是個老毛病,修一下就好。
編輯 /etc/init/tftpd-hpa.conf ,修改它錯誤的初始條件。

#start on runlevel [2345] # the original line which is wrong
start on (filesystem and net-device-up IFACE!=lo)

service tftpd-hpa restart

2013年1月18日星期五

install FreeNX on Ubuntu


How to install FreeNX on Ubuntu 12.04 Precise Pangolin source

Ask anyone who knows me and they will tell you that I am a vocal (and perhaps tireless) advocate of FOSS/GNU/Linux. I loves me some FOSS and GNU/Linux and I really like to help others with it as well!

So after writing my post: How to install NX Free Edition on Ubuntu 12.04 Precise Pangolin, I will follow it up with a story about FOSS. In this post, I will guide you through some easy instructions for installing the GPL,FOSS NX server variant called FreeNX, and the FOSS "qtnx" client that is used to connect to the FreeNX server.

The main difference is that, unlike NX Free Edition, which is licensed as proprietary ( 2 connections limit), FreeNX and qtnx are completely Free Open Source Software (FOSS, GPL)! Sounds good right? It's music to my ears. Afterall, this FOSS/GNU/Linux stuff makes the Technical world go around for everyone.

Update 01/02/13: Want to try something easier? Simply install xrdp:
1.) sudo apt-get install xrdp
2.) Add this to the ~ of the user you plan on logggin in with:
echo "gnome-session --session=ubuntu-2d" > ~/.xsession
3.) sudo /etc/init.d/xrdp restart
4.) Connect to your xrdp host from GNU/Linux with rdesktop , or from win with windows-key+R, mstsc /v:

So here are the simple instructions (and a couple of tweaks) that I used to install FreeNX on Ubuntu 12.04 GNU/Linux:

First, you need to add the freenx-team PPA for Ubuntu 12.04 GNU/Linux. Hit CTRL + ALT + t to get your Terminal, then type or paste in the command below, then hit Enter, then hit Enter to confirm the addition of the new source:
sudo add-apt-repository ppa:freenx-team
Next, update your sources list, then install the FreeNX server software (there are two commands below, the 2nd only runs if 1st is successful). After verifying that no important packages will beremoved, hit Y then enter to install FreeNX server:

sudo apt-get update && sudo apt-get install freenx

Next, as noted in the community documentation for installing FreeNX - download the missing nxsetup script, untar it, then copy it to /usr/lib/nx (the command below is one entire line that runs 3 commands and ends with /usr/lib/nx):
wget https://bugs.launchpad.net/freenx-server/+bug/576359/+attachment/1378450/+files/nxsetup.tar.gz && tar xvf nxsetup.tar.gz && sudo cp nxsetup /usr/lib/nx
Now, run the nxserver setup script. I chose to use the parameter to install the default NoMachine provided encryption keys during this command so the NoMachine win-clients can connect as well as qtnx:
sudo /usr/lib/nx/nxsetup --install --setup-nomachine-key
At this point, you have FreeNX server installed, but now you'll want to configure the FreeNX server to configure clients to use ubuntu-2d session:
echo -e "\n#Use unity 2d for client sessions\nCOMMAND_START_GNOME='gnome-session --session=ubuntu-2d'"|sudo tee -a /etc/nxserver/node.conf


Next, restart the FreeNX server to ensure it takes in the .conf file:
sudo /etc/init.d/freenx-server restart
That's it for the FreeNX server, now let's move on to the client. First, install the 'qtnx' package on Ubuntu 12.04 so we can have a client application to access the FreeNX server. You'll have to launch the Ubuntu Software Center, then click 'Edit > Software Sources' from the top menu. Then place a check by "Community-maintained free and open-source software (universe). Also, uncheck "Cdrom with Ubuntu 12.04" if it's checked. Then close the Software Sources dialog and the Ubuntu Software Center.
Now, run the commands to update your sources and install the qtnx application from the terminal (CTRL + ALT + t):
sudo apt-get update && sudo apt-get install qtnx
Ok, from the Unity menu or the CLI, start the 'qtnx' application. Enter the username/password for a user on the server, set the speed to LAN, then click configure. On the configuration dialog, set a name for the prfile, the hostname(or IP address) for the FreeNX server machine, the client resolution (I used 1024x768), network speed (LAN), and set the platform type to GNOME (see the example screenshot below).


Note: For the non-GNU/Linux clients, you can use nomachine.com's NX Client Free to connect to the server. Just use GNOME as the session.

That's it! Get your FreeNX connection on!
As for the version I tested with, it's: nxserver --version 3.2.0-74-SVN OS (GPL, using backend: 3.5.0)

Extra Tip: If for some reason your client wouldn't connect after testing, try deleting the entries in the ~/.nx directory. I'm not sure why this would help at all in most cases but it seemed to work for me. 



Extra Tip 2: If your clients are seeing the Network Manager 'Edit' buttons as greyed out while connected - have a look at this workaround: http://ubuntuforums.org/showthread.php?t=1616355




Install FreeNX server on Ubuntu 10.04 (Lucid), 10.10 (Maverick) or 11.04 (Natty)

  1. Enable the repository:
    sudo add-apt-repository ppa:freenx-team
  2. If you're using 10.10 Maverick, run
    sudo sed -i 's/maverick/lucid/g' /etc/apt/sources.list.d/freenx-team-ppa-maverick.list
  3. If you're using 11.04 Natty, run
    sudo sed -i 's/natty/lucid/g' /etc/apt/sources.list.d/freenx-team-ppa-natty.list
  4. Update the repository:
    sudo apt-get update
  5. Install FreeNX:
    sudo apt-get install freenx
  6. Download the setup script:
    cd /tmp;
    wget https://bugs.launchpad.net/freenx-server/+bug/576359/+attachment/1378450/+files/nxsetup.tar.gz;
    tar zxvf nxsetup.tar.gz
  7. Install the setup script:
    sudo cp nxsetup /usr/lib/nx/nxsetup
  8. Run the setup script:
    sudo /usr/lib/nx/nxsetup --install