From: Jun'ya Shimoda Date: 2011-10-10T14:00:43+09:00 Subject: [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/