Total Pageviews

2015/08/24

[iReport] Custom Format

Problem
The original setting interest-related column in this report is as follows:

The value of interest-related column's show 5 decimal places:

But the foregoing report does not meet user's requirement. The digits to the right of the decimal point in a number determined by the data. If the value is 0.55000, show 0.55; if the value is 0.62690, show 0.6269. The correct report is as following:


Solution
Use custom format instead. The configuration is as bellows: 

2015/08/21

一家公司手上應該有多少現金才夠

一家公司手上應該有多少現金才夠?

為什麼這個問題會重要?
因為若市場發生劇烈變化,很可能會因為手上現金不夠,導致無法度過難關,公司因此倒閉

Graham於Security Analysis一書中有提到兩個原則
1. 流動資產至少是流動負債的兩倍
2. 流動資產扣除庫存後,至少要等於流動負債,超過越多越好

以台股為例,我們針對台灣50成分股,依據EPS由高到低,找出最賺錢的前十大的公司如下 (包含股價、EPS、本益比):

接下來到 http://goodinfo.tw/ 找出這十家公司的流動資產與流動負債


上述十家公司的流動資產、流動負債以及流動資產與負債比如下:

由上表可以得知,可成、台積電與鴻準這三家公司有滿足第一個條件。
一般說來,比率越高,代表企業資產的變現能力越強,短期償債能力也越強;反之則弱。

接下來,一樣到 http://goodinfo.tw/ 查詢存貨資訊


上述十家的庫存以及流動資產減去庫存、流動負債後的資訊如下:

從以上表格中的數字可以得知,除了其中兩家以外,都有符合第二個條件

綜合兩個條件來看,以財務健康程度來說,以可成、台積電與鴻準這三家公司最健康,其變現能力與短期償債能力都是最強的


Reference
[1] http://goodinfo.tw/
[2] http://www.fivedream.com/page1.aspx?no=221266&step=1&newsno=36291

2015/08/17

[Oracle] LISTAGG cannot handle NVARCHAR2

Problem
Assume this following SQL statement will get agency name
1
2
3
4
SELECT age, agency
FROM ave011fa
WHERE fyr='104'
AND age IN ('0240005', '0000000', '2971021');

The search result is as bellows:

If we would like to concatenate multiple agencies into one row, we need to make good use of LISTAGG function.

Therefore, the SQL statement will modify as following:
1
2
3
4
5
6
SELECT fyr,
       LISTAGG(AGENCY, ';') WITHIN GROUP (ORDER BY fyr) AGENCY
FROM ave011fa
WHERE fyr='104'
AND age IN ('0240005', '0000000', '2971021')
GROUP BY fyr;


But the agency name's characters are broken

Solution
Owing to agency column's data type is NVARCHAR2, LISTAGG function cannot handle NVARCHAR2 properly

So you need to cast agency to a char to fix this problem

1
2
3
4
5
6
SELECT fyr,
        LISTAGG(TO_CHAR(AGENCY), ';') WITHIN GROUP (ORDER BY fyr) AGENCY
FROM ave011fa
WHERE fyr='104'
AND age IN ('0240005', '0000000', '2971021')
GROUP BY fyr

Then we can get the expected result:


Reference
[1] http://stackoverflow.com/questions/15304648/oracle-sql-developer-3-1-07-extra-spaces-between-characters-using-listagg
[2] http://www.techonthenet.com/oracle/functions/listagg.php

2015/08/16

[Programming] 提高控制流程可讀性

最近閱讀了易讀程式之美一書,在提高控制流程可讀性此章節提到幾個重點

  1. 在使用if-else判斷式時,先處理肯定條件;先處理簡單的情況,必較能在畫面中同時呈現if與else區塊,在閱讀上很有幫助;先處理比較有趣或明顯的情況
  2. 縮短其他人理解程式所需的時間,比減少程式碼行數來得重要
  3. 只有在最簡單的情況下使用三元運算子(ternary operator),複雜的情況還是盡量使用if / else
  4. 避免使用do / while loop
  5. C++的創造者Bjarne Stroustrup說,在我的個人經驗裡,do / while 敘述經常是錯誤與誤解的來源,我寧願把條件式列在最前面,總而言之,我會盡量避免使用do / while 敘述
  6. 修改程式碼時要以全新的角度審視,退一步以整體的角度考慮程式碼
  7. 盡量消除loop中的巢狀結構,因為巢狀結構可讀性較差


Example1. 如果是很簡單的情況,用ternary operator是ok的
1
timeStr += (hour >= 12) ? "pm" : "am";

若是遇到較複雜的狀況,如下:
1
int result = exponent >= 0 ? mantissa * (1 << exponent) : mantissa * (1 << -exponent);

則建議將上述的表示方式改用if-else的方式表達
1
2
3
4
5
if (exponent >= 0) {
 result = mantissa * (1 << exponent);
} else {
 result = mantissa * (1 << -exponent);
}


Example2. 盡量避免用do-while

如原本為do-while的表示方式
1
2
3
4
5
int sum = 0;
int count = 1;
do {
    sum += count++;
} while (count <= 10);

除非有什麼特別原因,盡量改成while-loop
1
2
3
4
int sum = 0, count = 1;
while (count <= 10) {
 sum += count++;
}









2015/08/13

Promises in AngularJS

Problem
We would like to update the value which be marked by red rectangle in the following screenshot:


The value will be updated from 20 to 30:



After clicked save button, it will do search at once. The value seems does not be updated successfully, because the search result does not show the up-to-date value :

But as I click search button again, it show correct value.


original JavaScript code:
$scope.save = function(){            
    //do save
    fms426qService.save($scope.fms426qUpdateGridData);
    //do query
    $scope.query();
};


Solution
The root cause is the Javascript code had executed query before it finish its save action. Hence, you should make sure do query after save.

You can use Promises in AngularJS. The most powerful features of promises is the ability to chain them together. This allows the data to flow through the chain and be manipulated and mutated at each step. 

Therefore, you should update JavaScript code as bellows::
$scope.save = function(){            
    //do save
    fms426qService.save($scope.fms426qUpdateGridData).then(function(response) {
        //do query after save
        $scope.query();
    });
};


Reference
[1] http://andyshora.com/promises-angularjs-explained-as-cartoon.html
[2] https://thinkster.io/a-better-way-to-learn-angularjs/promises

2015/08/03

java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result

Problem
Here is my code snippet.

If amtIn is 100 and amtOut is 20, then it works fine.
1
2
3
4
5
6
  private BigDecimal toRate(final BigDecimal amtIn, final BigDecimal amtOut) {
      if (null == amtIn || null == amtOut) {
          return null;
      }
      return amtIn.divide(amtOut).multiply(new BigDecimal(100));
  }


But if amtIn is 100 and amtOut is 120, then it will throw exception unexpectedly
1
2
3
4
16:40:15,812 INFO  [stdout] java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result.
16:40:15,812 INFO  [stdout]   at java.math.BigDecimal.divide(BigDecimal.java:1616) ~[na:1.7.0_25]
16:40:15,812 INFO  [stdout]   at gov.nta.dbm.service.Dbm034eService.toRate(Dbm034eService.java:264) ~[dbm-service-1.0.0-SNAPSHOT.jar:1.0.0-SNAPSHOT]
16:40:15,812 INFO  [stdout]   at gov.nta.dbm.service.Dbm034eService.modify(Dbm034eService.java:359) ~[dbm-service-1.0.0-SNAPSHOT.jar:1.0.0-SNAPSHOT

Solution
According to JavaDoc...
When a MathContext object is supplied with a precision setting of 0 (for example, MathContext.UNLIMITED), arithmetic operations are exact, as are the arithmetic methods which take no MathContext object. (This is the only behavior that was supported in releases prior to 5.)
As a corollary of computing the exact result, the rounding mode setting of a MathContext object with a precision setting of 0 is not used and thus irrelevant. In the case of divide, the exact quotient could have an infinitely long decimal expansion; for example, 1 divided by 3.
If the quotient has a nonterminating decimal expansion and the operation is specified to return an exact result, an ArithmeticException is thrown. Otherwise, the exact result of the division is returned, as done for other operations.

Owing to 100/120 has a nonterminating decimal expansion, so it will throw java.lang.ArithmeticException: Non-terminating decimal expansion; no exact representable decimal result

To resolve this problem, you can set precision to 2, and set rounding mode to RoundingMode.HALF_UP (precision and rounding mode depends on your requirement)
1
2
3
4
5
6
  private BigDecimal toRate(final BigDecimal amtIn, final BigDecimal amtOut) {
      if (null == amtIn || null == amtOut) {
          return null;
      }
      return amtIn.divide(amtOut, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100));
  }

Reference
[1] http://docs.oracle.com/javase/7/docs/api/java/math/BigDecimal.html
[2] http://elie2201.blogspot.tw/2012/03/bigdecimal-non-terminating-decimal.html

[Oracle to SQL Server Migration] Outer Join

In Oracle, we use outer join, (+), in the SQL statement as bellows:
SELECT A.MGE_TYPE,
       B.ORG_TYPE,
       F_DBM_FIND_CODE_NM('ORGTP', B.ORG_TYPE) AS ORG_NAME,
       (A.IN_AMT/A.OUT_AMT) * 100 AS RATE,
       (C.IN_AMT/C.OUT_AMT) * 100 AS RATE1_YEAR,
       (D.IN_AMT/D.OUT_AMT) * 100 AS RATE2_TEAR
FROM DBM034FA A,
     DBM030FA B,

  (SELECT *
   FROM DBM034FA
   WHERE TO_CHAR(STA_DATE,'YYYY') = :year1) C,

  (SELECT *
   FROM DBM034FA
   WHERE TO_CHAR(STA_DATE,'YYYY') = :year2) D
WHERE A.AGE = B.AGE
  AND A.STA_DATE = B.STA_DATE
  AND A.AGE = C.AGE(+)
  AND A.FUND_ID = C.FUND_ID(+)
  AND A.MGE_TYPE=C.MGE_TYPE(+)
  AND A.AGE = D.AGE(+)
  AND A.FUND_ID = D.FUND_ID(+)
  AND A.MGE_TYPE=D.MGE_TYPE(+)
  AND TO_CHAR(A.STA_DATE,'YYYY')=:year

Owing to (+) is the specific approach to do outer join in Oracle, it does not work in SQL Server.
Hence, the foregoing SQL statement should be translated as following:
SELECT A.MGE_TYPE,
       B.ORG_TYPE,
       AP_NTA.F_DBM_FIND_CODE_NM('ORGTP', B.ORG_TYPE) AS ORG_NAME,
       (A.IN_AMT/A.OUT_AMT) * 100 AS RATE,
       (C.IN_AMT/C.OUT_AMT) * 100 AS RATE1_YEAR,
       (D.IN_AMT/D.OUT_AMT) * 100 AS RATE2_TEAR
FROM DBM034FA A
INNER JOIN DBM030FA B ON A.AGE = B.AGE
AND A.STA_DATE = B.STA_DATE
AND CONVERT(VARCHAR(4), A.STA_DATE, 112)=:year
LEFT OUTER JOIN
  (SELECT *
   FROM DBM034FA
   WHERE CONVERT(VARCHAR(4), STA_DATE, 112) = :year1) C ON A.AGE = C.AGE
AND A.FUND_ID = C.FUND_ID
AND A.MGE_TYPE=C.MGE_TYPE
LEFT OUTER JOIN
  (SELECT *
   FROM DBM034FA
   WHERE CONVERT(VARCHAR(4), STA_DATE, 112) = :year2) D ON A.AGE = D.AGE
AND A.FUND_ID = D.FUND_ID
AND A.MGE_TYPE=D.MGE_TYPE

Reference
[1] https://technet.microsoft.com/zh-tw/library/ms187518(v=sql.105).aspx



2015/08/01

[閱讀筆記] Steve Jobs在想什麼


  1. 向外救援,別把重擔獨自攬下。
  2. 保持聚焦,別讓商品特色功能浮濫化。保持事情的精簡,這對已經過於複雜的科技世界來說,會是個優點。
  3. 聚焦於你擅長的事情上,其他的交給別人全權處理。
  4. Osborne Effect:一家公司如果提早宣布處於開發階段的優質技術,無疑是一種自殺行為。
  5. 避免Osborbe Effect:別提前將新的好東西洩漏出去,除非已經準備出廠上市,免得顧客為了等新東西而不再買現有的貨。
  6. 最重要的決策不在於你決定做的那些事情,而在於你決定不做的。
  7. 研究發現,被使用者退回的產品中,有將近一半沒故障,只是新的使用者搞不清楚怎麼使用而已。
  8. 藝術和科技的創作就像是個人的表現力。藝術家不可能透過一場焦點團體討論來創作一幅畫。
  9. 很多時候人們不會知道自己想要什麼,除非你秀給他們看。
  10. Steve Jobs就是蘋果的一人焦點團體。
  11. 別怕從頭開始。
  12. 所謂精簡化,就是把複雜的事情解決掉。
  13. 當你在看某個問題時,心想這個東西很簡單,這就代表你根本不了解問題到底有多複雜。
  14. 設計只的是功能上的設計,不是形式而已。對Jobs來說,設計就是指產品的功能運轉方式。
  15. 把每個人都找進來。設計不只是設計師的工作,工程師、程式設計人員和行銷人員都可以幫忙發想產品要如何運作。
  16. Jobs不會故意想要設計出『好用』的產品,這種『好用性』是從設計過程中慢慢成形的。
  17. 一家新創業公司的成功與否,得看他推出的第一個產品而定。
  18. 新創業的公司必須一出手就成功,否則就會一敗塗地。如果你挑對產品,你的勝算就大了。
  19. Apple向來以他的生活型態廣告聞名,從不像其他人都是在廣告裡強調機器的速度、功能和特色,反而採取生活型態行銷。
  20. Apple的iPod廣告極為成功,他的表現手法就是讓年輕人盡情享受戴在頭上的音樂,一字不提iPod的硬體容量。
  21. 小而美的工作團隊。Jobs不喜歡團隊規模超過百人以上,因為擔心失焦或無法管理。
  22. 別相信『唯命是從』的人。爭辯可以激盪出創意,Jobs希望夥伴們質疑他的想法。
  23. 找到你對工作的熱情。
  24. 使點狠招,把事情辦好。
  25. 就算是看似不可能的事情也要堅持下去。Jobs知道再棘手的問題最終都會獲得解決。
  26. 創新和你的研發基金有多雄厚沒關係。當年Apple推出Mac時,IBM花的研發基金至少是Apple的一百倍,所以這和錢的多寡無關,和你有什麼人才,你的領導方式,以及你有多用心有關。
  27. 權威分析家總是將Apple歸這種公司歸類成擅長product innovation,Dell則之類的則是落實business innovation的企業。在商業史上,最成功的公司都不是production innovation者,而是那些懂得開發出business innovation 的公司。
  28. 講到創新,Jobs很喜歡引用畢卡索的名言:好的藝術家抄;偉大的藝術家偷。對此,Jobs有他的補充說法:『所以我們向來對偷取偉大的點子這件事,一點都不覺得可恥。』
  29. 創新就是創造力,把一些東西用讀到的方法整合在一起。創意就是將事物連結在一起。
  30. MagSafe電源轉換器,他被設計的可以輕易與電線分離,以免電腦被摔到地上。這是Apple從日本電鍋身上找到的點子,多年來,基於同樣理由,日本電鍋一直配有詞性的電源轉換器,防止小孩辦到電線時滾水灑出來。
  31. 不要對顧客視而不見。Cube電腦會慘敗,是因為他是為設計師所製作的,不是為了顧客。
  32. 不要刻意想創新,妄想創新系統化。
  33. 專注在產品上。產品是凝聚一切的萬有引力。
  34. 竊取。要敢厚顏無恥地竊取別人的好點子。
  35. 連結。對Jobs來說,所謂創造力就是把一些東西連結在一起。
  36. Apple II電腦之所以熱賣,靠的就是第一套試算表軟體VisiCalc。任天堂之所以成為遊戲市場的主力產品,都是歸功於他的Mario Brothers電玩遊戲。而Mac也是在Adobe開發出文件和印表機專業的標準語言PostScript程式之後,才開始一飛沖天,開啟了桌上排版作業的革命。
  37. 電腦即將成為『生活型態』的重要科技,不再只是『工作上』的重要科技。
  38. 如果你錯失了機會,更要賣力迎頭趕上。
  39. 別擔心技術從哪裡來,重要的是技術的結合。
  40. 槓桿運用你的專業技術,絕對不要從零開始。
  41. 相信團隊。iPod沒有所謂的始祖,也沒有所謂的『iPod之父』。他從來就不是一個人的成就,成功永遠來自於眾多發明者。
  42. 從個人電腦的歷史來看,硬體的成功與否,關鍵往往卡在他能否擁有獨一無二的軟體:電子試算表VisiCalc之於Apple II電腦,版面設計軟體Aldus Pagemaker和桌上排版系統之餘Mac,Halo遊戲之於Xbox
  43. 硬體和軟體的一體化,可以造就出更容易管理和掌控的系統。封閉的系統雖然會侷限你的選擇,卻比較穩定可靠;相形之下,開放的系統就顯得比較脆弱和不可靠,這就是自由的代價。
  44. Microsoft這種想讓硬體變得更有相容性的主動精神『Plug and Play』,反倒變成『Plug and Pray』的戲謔之語,因為有太多軟硬體的結合,後果如何很難預料。