https://teratail.com/questions/30454
で指摘があったので、度数法で書きかえました。
無駄な書き方をしていないでしょうか?
ご意見でもよろしいので返事いただければ幸いです。
ruby
1require "bigdecimal/math" 2include BigMath 3 4def sin_deg(m, n) 5 return '0' if n % 180 == 0 6 sin(BigDecimal((PI(m) * n / 180.0).to_s), m).to_s("F")[0..m] 7end 8 9p sin_deg(100, 2) 10p sin_deg(100, 2r / 3) 11p sin_deg(100, 2.4) 12p sin_deg(100, 180)
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
なんとなーく、モジュールにしてみました。
Ruby
1require 'bigdecimal' 2require 'bigdecimal/math' 3 4module BigMath2 5 module_function 6 def rad2deg(x, prec) 7 (x * (180 / BigMath.PI(prec + 1))).round(prec) 8 end 9 10 def deg2rad(x, prec) 11 (x * (BigMath.PI(prec + 1) / 180)).round(prec) 12 end 13 14 def sin_deg(x, prec) 15 BigMath.sin(deg2rad(x, prec + 1), prec + 1).round(prec) 16 end 17 18 def cos_deg(x, prec) 19 BigMath.cos(deg2rad(x, prec + 1), prec + 1).round(prec) 20 end 21 22 def atan_deg(x, prec) 23 BigMath.atan(deg2rad(x, prec + 1), prec + 1).round(prec) 24 end 25end 26 27if __FILE__ == $0 28 list = [0, 2, 2r / 3, 2.0 / 3, 2.4] 29 13.times do |i| 30 list << i * 30 31 end 32 precision = 20 33 list.each do |x| 34 puts "sin(#{x}°) = #{BigMath2.sin_deg(x, precision).to_s('f')}" 35 end 36 list.each do |x| 37 puts "cos(#{x}°) = #{BigMath2.sin_deg(x, precision).to_s('f')}" 38 end 39 list.each do |x| 40 puts "atan(#{x}°) = #{BigMath2.sin_deg(x, precision).to_s('f')}" 41 end 42end
有効数字+1で計算していますが、これでいいのかはちょっとわかりません。四則演算なら+1で大丈夫だと思いますが、sinとかは有効数字はちょっと違うようですのでこれが正確であるとは限りません。。BigDecimalへの四則演算はBigDecimalを返しますので、再度BigDecimalで囲む必要はありません。文字列では無くBigDecimalを返すようにしています。理由はそのままでは数値演算に使えないからです。場合分けは特にしていません。そのため、+0.0と-0.0は区別されます。最後に桁はroundで丸めています。切り捨てではありません。引数の順番はBigMath.#sinに合わせました。cosとatanはおまけです。
投稿2016/03/27 08:54
総合スコア21733
0
2つの変更をしてみました。
- 桁数指定は省略をできるようにした。
- 計算結果が 1, -1 の場合は "1", "-1" を返すようにした。
ruby
1require 'bigdecimal/math' 2include BigMath 3 4# sin(n) の値を m 桁の文字列で返す。 5# ただし、sin(n) の値が 0, 1 の場合は '0', '1' を返す。 6def sin_deg(n, m = 100) 7 return '0' if n % 180 == 0 8 return '1' if n % 360 == 90 9 return '-1' if n % 360 == 270 10 sin(BigDecimal((PI(m) * n / 180)), m).to_s('F')[0..m] 11end 12 13p sin_deg(0) 14p sin_deg(2) 15p sin_deg(2r / 3) 16p sin_deg(2.0 / 3) 17p sin_deg(2.4) 18 19puts 2012.times { |x| 21 deg = 30 * x 22 p "#{deg} -> #{sin_deg(30 * x, 20)}" 23} 24
実行結果
$ ruby 1.rb "0" "0.034899496702500971645995181625332937354824576043296871425005766942084051213821325451123151459028565" "0.011635265801397014602667654994549171911797803980910040236314916774919405972045591895078598117351329" "0.011635265801397013439193583545769218632825365782088875348558795639677430603629301160884544931328993" "0.041875653729199629552835351557732683223252479096878867471484088777896653959256704844944845828278283" "0 -> 0" "30 -> 0.5000000000000000000" "60 -> 0.8660254037844386467" "90 -> 1" "120 -> 0.8660254037844386467" "150 -> 0.4999999999999999999" "180 -> 0" "210 -> -0.499999999999999999" "240 -> -0.866025403784438646" "270 -> -1" "300 -> -0.866025403784438646" "330 -> -0.500000000000000000"
投稿2016/03/26 22:03
総合スコア22324
0
katoy さんの回答をもとに以下のようにしてみました。
sin(a/b π) が有理数になるのは自明な時
(http://note.chiebukuro.yahoo.co.jp/detail/n3993)
しかないのでこれでいいでしょう。
ruby
1require 'bigdecimal/math' 2include BigMath 3 4def sin_deg(n, m = 100) 5 k = n % 360 6 case k 7 when 0, 180 ; return '0' 8 when 30, 150 ; return '0.5' 9 when 90 ; return '1' 10 when 210, 330 ; return '-0.5' 11 when 270 ; return '-1' 12 else ; return sin(BigDecimal(PI(m) * n / 180), m).to_s('F')[0..m] 13 end 14end 15 16p sin_deg(2) 17p sin_deg(2r / 3) 18p sin_deg(2.4) 19p sin_deg(180) 20 21puts 2213.times{|x| 23 deg = 30 * x 24 p "#{deg} -> #{sin_deg(30 * x, 20)}" 25}
出力結果
"0.034899496702500971645995181625332937354824576043296871425005766942084051213821325451123151459028565"
"0.011635265801397014602667654994549171911797803980910040236314916774919405972045591895078598117351329"
"0.041875653729199629552835351557732683223252479096878867471484088777896653959256704844944845828278283"
"0"
"0 -> 0"
"30 -> 0.5"
"60 -> 0.8660254037844386467"
"90 -> 1"
"120 -> 0.8660254037844386467"
"150 -> 0.5"
"180 -> 0"
"210 -> -0.5"
"240 -> -0.866025403784438646"
"270 -> -1"
"300 -> -0.866025403784438646"
"330 -> -0.5"
"360 -> 0"
投稿2016/03/27 07:41
編集2016/03/27 08:14総合スコア233
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。