awkで巨大な数字を取り扱う
Pocket

先日のシェル芸勉強会において、awkで巨大な数字を取り扱うという内容があった。
awkでは、巨大な数字を扱おうとすると以下のようなエラーが出力されることがあるのだけど、これを回避する方法について考えるという内容だった。

$ echo|awk '{print(999^300)}'
+inf

 

Stack Overflowとかを漁っていると、どうも53bit分までのデータしか扱えないため、それ以上の数字になるとinfとして扱われてしまっている模様。

 

1. gawkを使う場合

よく利用されているLinuxディストリビューションやMacで通常利用されているawkはGNU AWKになると思うのだが、awkにもいくつか種類がある。
で、そのうちのgawkなら-Mオプションを付与することで大きな数字を使った処理が可能になる。(よく使われているディストリビューションならgawkは最初から入っていると思う)

echo|gawk -M '{print(999^300)}'
$ echo|gawk -M '{print(999^300)}'
740707032156099464825492750125498782923874997114130170806961001465301947538727830598812870497467597333002429369381746413743021176620344898655207751051108708579287880019440359948243215080720463734669832067616376175341390825421213050005452748768407493902025373936876451797400970604198304852801661619040441348084547289450744175249347732702399917029521145703104814593938370882400665603350003537154659459564176427697064774096972412730972085462563537635168332560169315559224328701513052621237294170155723669297217400292632571256751580897716347362490700335631129107897897453613649989596616742433021575662612278745780586699903776370240325588753171590515699672270878538542792753250573616314228667632063973166085995878058059053688620177939547636928933182592888373343798594262891750605297854013386330575193419486800497723897287405936162673840121331123962104618131416258947795731421639516864193226719944849700001
Sponsored Links

2. 外のコマンドに処理させる

処理している内容にもよるが、もしbcなどの外部に出せる処理ならコマンドを組み立てて処理するという方法もあるだろう。
普通にWEBシステムとかそういうのだとコマンドインジェクション作り込む発想だからあんまりよろしくない方法だと思うんだけど、awkを使う場面って大体コンソールでの操作だと思うのでまぁこの場合は影響ないだろう(多分)。

echo|gawk -M '{print("999^300")}'|bc
echo|gawk -M '{print("bc <<<999^300")}'|bash
$ echo|gawk -M '{print("999^300")}'|bc
74070703215609946482549275012549878292387499711413017080696100146530\
19475387278305988128704974675973330024293693817464137430211766203448\
98655207751051108708579287880019440359948243215080720463734669832067\
61637617534139082542121305000545274876840749390202537393687645179740\
09706041983048528016616190404413480845472894507441752493477327023999\
17029521145703104814593938370882400665603350003537154659459564176427\
69706477409697241273097208546256353763516833256016931555922432870151\
30526212372941701557236692972174002926325712567515808977163473624907\
00335631129107897897453613649989596616742433021575662612278745780586\
69990377637024032558875317159051569967227087853854279275325057361631\
42286676320639731660859958780580590536886201779395476369289331825928\
88373343798594262891750605297854013386330575193419486800497723897287\
40593616267384012133112396210461813141625894779573142163951686419322\
6719944849700001
                                                                                                                                                                             
$ echo|gawk -M '{print("bc <<<999^300")}'|bash
74070703215609946482549275012549878292387499711413017080696100146530\
19475387278305988128704974675973330024293693817464137430211766203448\
98655207751051108708579287880019440359948243215080720463734669832067\
61637617534139082542121305000545274876840749390202537393687645179740\
09706041983048528016616190404413480845472894507441752493477327023999\
17029521145703104814593938370882400665603350003537154659459564176427\
69706477409697241273097208546256353763516833256016931555922432870151\
30526212372941701557236692972174002926325712567515808977163473624907\
00335631129107897897453613649989596616742433021575662612278745780586\
69990377637024032558875317159051569967227087853854279275325057361631\
42286676320639731660859958780580590536886201779395476369289331825928\
88373343798594262891750605297854013386330575193419486800497723897287\
40593616267384012133112396210461813141625894779573142163951686419322\
6719944849700001

 

基本的にはgawkで処理するのがいいと思う。
諦めてPerlでやるという方法もあるけど、そこは状況に応じて臨機応変に対応する感じだろうか…。

 

Pocket

Written by blacknon

インフラエンジニア(…のつもり)。 仕事で使うならクライアントはWindowsよりはUNIXの方が好き。 大体いつも眠い。

Leave a Comment

メールアドレスが公開されることはありません。

*