2011年10月10日

[ruby-list:48458] Re: 1.8.7と1.9.2の挙動の違いについて

下田です。

皆様、たくさんのお返事をいただきありがとうございます。

挙動の違いからロジックに話題が移ってしまいましたが
この話題のきっかけとまとめをしたいと思います。

この話題に行き着いたきっかけは

そのプログラマー初級者の人が勤める会社の
新入社員用の試験問題として出されたので
これを理解したいとの話がそもそもの始まりでした。
回答するに当たって言語は問わないとの事だったので
多分Rubyでしか使えないロジックよりも一般解に導くように
教えるのが良いだろうと判断して彼と議論してました。

そこで今回の疑問を投稿することになったのですが
1.8.7と1.9.2の挙動の違う点が分かりました。
str[0], str.slice(0)
です。これを私は最初の「文字」を抽出してくれるものと思い
実際1.9.2では最初の文字を抽出してくれるのですが
1.8.7では最初の「バイト」を得るそうです。
だから
str[0, 1], str.slice(0, 1)
にすれば、互換性が保たれます。
引数によって戻り値が文字だったり数値だったりするのが予想外でした。
個人的にはあまり良い事だとは思えませんが・・・


プログラム1
> 私ならこう書く、という話になりますが、とりあえず下の桁から足すような形に
> 展開してもいいならこんな感じに、
>
> def calc(prm)
> if prm < 10 then
> prm
> else
> prm % 10 + calc(prm / 10)
> end
> end
文字列を処理するより難解ですが
文字と数値の変換が入らないので早そうです。
賢いロジックですね。


プログラム2
> def calc(prm)
> if prm < 10 then
> prm
> else
> prm.to_s[0, 1].to_i + calc(prm.to_s[1 .. -1].to_i)
> end
> end
初級者には一番妥当な解だと思います。


プログラム3
> もちろんこんな解もありますが、
> prm.to_s.each_char.map {|c| c.to_i }.inject(:+)
これは試験官に理解できるんでしょうか・・・


> それからprintfに渡す式をリテラル式以外にするのはやめましょう。
> printfの第一引数は、フォーマットを指定する文字列ですから、うっかり
> % が入っている文字列を渡すと変なことになります。
> 改行がいらなければprintを、また、わざわざ + "\n" と書くぐらいなら
> putsを使いましょう。
わかりました。

> prmという引数名も、パラメータ、かと思いますが、よくありません。
> argなら、慣用的によく使われているという理由で使う理由がありますが、
> prmはそういうこともないし、「パラメータ」だけではその中身の意味を、
> ほとんどあらわしてないからです。
> 一文字変数はよくない、などと言われますが、数を意味する n 、文字列を
> 意味する s などは立派に意味があり、このくらいの短いまとまった部分で
> あれば、むしろ使うほうが良い、と私は考えます。
なるほど。確かにそうですね。


色々なロジックを教えて頂いたので
ついでに下記のロジックでパフォーマンスを測定してみました。
----------
data = ARGV[0].to_i#必要なら
start = Time.now
99999.times do
puts (calc data).to_s
end
p Time.now - start
----------

プログラム1
約0.37秒

プログラム2
約0.63秒

プログラム3
約0.62秒

という結果になりました。
やはり数値文字列変換が入らないのは強いですね。

以上まとめでした。
たくさんのお返事ありがとうございました。
またよろしくお願いします。

--
A A Name : 下田 純也 (Jun'ya Shimoda)
(o'.'o) _/ e-mail : jun-shimo@nifty.com
(> ~ <)/ Blog : http://d.hatena.ne.jp/JironBach/
Twitter: http://twitter.com/JironBach/

投稿者 xml-rpc : 2011年10月10日 14:00
役に立ちました?:
過去のフィードバック 平均:(0) 総合:(0) 投票回数:(0)
本記事へのTrackback: http://hoop.euqset.org/blog/mt-tb2006.cgi/106844
トラックバック
コメント
コメントする




画像の中に見える文字を入力してください。