質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

3回答

1905閲覧

度数法でsin を求めるには?

manman

総合スコア233

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2016/03/26 15:37

編集2016/03/26 15:38

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ページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答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

raccy

総合スコア21733

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

2つの変更をしてみました。

  1. 桁数指定は省略をできるようにした。
  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

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

manman

2016/03/27 01:30

PI を使っているので、前回のようにto_s しなくても良さそうですね。 細かいことを言って悪いのですが、括弧が多い気がします。sin(BigDecimal(PI(m) * n / 180), m).to_s("F")[0..m] でいいのでは?
katoy

2016/03/27 06:26

はい、余分なカッコが入ってしまっていました。 さらに言えば、0.4999... となる部分を 0.5000... となるようにしたいですね。
guest

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
manman

総合スコア233

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問