久々ですが問題です.
1. あるアンケートの設問で,「該当する」と回答した割合が14%だった.N≦100の範囲で,アンケートの回答者数を求めなさい.
2. あるアンケートの設問で,「該当する」と回答した割合が1%だった.N≦100の範囲で,アンケートの回答者数を求めなさい.
プログラムを書く前に,いくつか計算してみます.「14%」について,1/7 = 0.14285以下略なので,N=7は解になります.「1%」のほうは,1/100 = 0.01なので,N=100は当然,解です.
Nって何?という人がいるかもしれないので補足しておくと,統計処理の結果をグラフにする際,実数すなわち上の例では「アンケートの回答者数」のことを,とくに断ることなく「N=数」で表すことがあります.もう一つ補足ですが,ここでの「実数」は,real numberではなくactual count(あるいはactual number)といいます.
さて,この問題の厄介なところは,割合は,その分母と分子となる整数値があって初めて求められますが,問題文の通り,そのどちらも明示されていないということです.
それで,1/7 = 0.14285以下略を1/0.14285以下略 = 1と式変形できるので,「100/パーセンテージ」で求めればいいのかというと,不十分です.「1%」の問題で,67人中1人が「該当する」と回答したら,1/67 = 0.01492以下略で,パーセンテージにして小数点以下を四捨五入すれば1%となり,N=67も解になるわけです.
単純な割り算では求められないし,どうやらいくつも解があるようなので,プログラムを書いてループを回さないといけないなと思えてきます.
では,プログラムです.
#!/usr/bin/env ruby # actualcount1.rb class ActualCount def initialize(rate_, max_ = 100) @rate = rate_ @max = max_ end def get_actualcount 1.upto(@max) do |d| # (@rate-0.5)/@max≦n/d<(@rate0.5)/@max を満たす整数nを探す # 変形すると,(@rate*10-5)*d/(@max*10)≦n<(@rate*10+5)*d/(@max*10) n_min = ((@rate.to_f * 10.0 - 5.0) * d.to_f / (@max.to_f * 10.0)).ceil n_max = ((@rate.to_f * 10.0 + 5.0) * d.to_f / (@max.to_f * 10.0)).floor if n_min <= n_max n = n_min.to_i puts "Found! N=#{d}" puts " %d * %d / %d = %g -> %d" % \ [@max, n, d, @max.to_f * n.to_f / d.to_f, @rate] end end end end if __FILE__ == $0 max = (ARGV.shift || 100).to_i rate = (ARGV.shift || 14).to_i ActualCount.new(rate, max).get_actualcount end
実行結果は,「ruby actualcount1.rb」と「ruby actualcount1.rb 100 1」でご確認ください.100以下の範囲で,前者は52個,後者は34個の解(「実数」の候補)が出てきます.前者すなわち「14%」は,初めのうちは7の倍数かなと見ていくと,28のほかに29も,35のほかに36も37も解になることがわかります.後者すなわち「1%」では,67≦N≦100はすべて解になります.「14%」に戻ると,N=88,90は解ですが,間のN=89は解に含まれていません.
プログラムの勘所は,コメントに書いているとおり,=@rate, =@maxが与えられたときに,
を満たす分子n, 分母dの組を,dを1から@maxの範囲でループさせて求めることです.そのような整数n,dの組が見つかれば,その分母dが,求めるべきNの一つとなり,そのときのnは,「該当する」と回答した人の数になります.
dはループを回すことで常に整数になるので,nが存在するか否かだけを見ればいいわけです.これは,
- を満たす最小の整数をn_min
- を満たす最大の整数をn_max
としたとき,n_min≦n_maxとなるかどうかで判定できます.@rate=7, @max=100を固定して,
- d=6のときは, より, …解なし
- d=7のときは, より, …n=1が解
ということで,うまく解が求められそうです.
Rubyスクリプトについて,「to_f」でFloat型にしているので,そこに計算誤差が起こる可能性が一応はあります.ただし,maxが100や1000くらいなら,問題はなさそうです.
以下は,次回の予告編です.
3. あるアンケートの設問で,「該当する」と回答した割合が30.8%だった.N≦1000の範囲で,アンケートの回答者数を求めなさい.
答えは,「ruby actualcount1.rb 1000 308」で求められますが,たくさん出てきます.もう少しプログラムを修正して,この計算を,最近読んだある本に適用してみる予定です.
(2008年4月6日18:00ごろ:あちこち改訂しました.)