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

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

ただいまの
回答率

90.48%

  • Ruby

    7978questions

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

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

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 710

manman

score 258

https://teratail.com/questions/30454
で指摘があったので、度数法で書きかえました。
無駄な書き方をしていないでしょうか?
ご意見でもよろしいので返事いただければ幸いです。

require "bigdecimal/math"
include BigMath

def sin_deg(m, n)
  return '0' if n % 180 == 0
  sin(BigDecimal((PI(m) * n / 180.0).to_s), m).to_s("F")[0..m]
end

p sin_deg(100, 2)
p sin_deg(100, 2r / 3)
p sin_deg(100, 2.4)
p sin_deg(100, 180)
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+2

なんとなーく、モジュールにしてみました。

require 'bigdecimal'
require 'bigdecimal/math'

module BigMath2
  module_function
  def rad2deg(x, prec)
    (x * (180 / BigMath.PI(prec + 1))).round(prec)
  end

  def deg2rad(x, prec)
    (x * (BigMath.PI(prec + 1) / 180)).round(prec)
  end

  def sin_deg(x, prec)
    BigMath.sin(deg2rad(x, prec + 1), prec + 1).round(prec)
  end

  def cos_deg(x, prec)
    BigMath.cos(deg2rad(x, prec + 1), prec + 1).round(prec)
  end

  def atan_deg(x, prec)
    BigMath.atan(deg2rad(x, prec + 1), prec + 1).round(prec)
  end
end

if __FILE__ == $0
  list = [0, 2, 2r / 3, 2.0 / 3, 2.4]
  13.times do |i|
    list << i * 30
  end
  precision = 20
  list.each do |x|
    puts "sin(#{x}°) = #{BigMath2.sin_deg(x, precision).to_s('f')}"
  end
  list.each do |x|
    puts "cos(#{x}°) = #{BigMath2.sin_deg(x, precision).to_s('f')}"
  end
  list.each do |x|
    puts "atan(#{x}°) = #{BigMath2.sin_deg(x, precision).to_s('f')}"
  end
end


有効数字+1で計算していますが、これでいいのかはちょっとわかりません。四則演算なら+1で大丈夫だと思いますが、sinとかは有効数字はちょっと違うようですのでこれが正確であるとは限りません。。BigDecimalへの四則演算はBigDecimalを返しますので、再度BigDecimalで囲む必要はありません。文字列では無くBigDecimalを返すようにしています。理由はそのままでは数値演算に使えないからです。場合分けは特にしていません。そのため、+0.0と-0.0は区別されます。最後に桁はroundで丸めています。切り捨てではありません。引数の順番はBigMath.#sinに合わせました。cosとatanはおまけです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

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

  1. 桁数指定は省略をできるようにした。
  2. 計算結果が 1, -1 の場合は "1", "-1" を返すようにした。
require 'bigdecimal/math'
include BigMath

# sin(n) の値を m 桁の文字列で返す。
# ただし、sin(n) の値が 0, 1 の場合は '0', '1' を返す。
def sin_deg(n, m = 100)
  return '0' if n % 180 == 0
  return '1' if n % 360 == 90
  return '-1' if n % 360 == 270
  sin(BigDecimal((PI(m) * n / 180)), m).to_s('F')[0..m]
end

p sin_deg(0)
p sin_deg(2)
p sin_deg(2r / 3)
p sin_deg(2.0 / 3)
p sin_deg(2.4)

puts
12.times { |x|
  deg = 30 * x
  p "#{deg} -> #{sin_deg(30 * x, 20)}"
}


実行結果

$ 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/27 10:30

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

    キャンセル

  • 2016/03/27 15:26

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

    キャンセル

+1

katoy さんの回答をもとに以下のようにしてみました。
sin(a/b π) が有理数になるのは自明な時
(http://note.chiebukuro.yahoo.co.jp/detail/n3993)
しかないのでこれでいいでしょう。

require 'bigdecimal/math'
include BigMath

def sin_deg(n, m = 100)
  k = n % 360
  case k
    when 0, 180   ; return '0'
    when 30, 150  ; return '0.5'
    when 90       ; return '1'
    when 210, 330 ; return '-0.5'
    when 270      ; return '-1'
    else          ; return sin(BigDecimal(PI(m) * n / 180), m).to_s('F')[0..m]
  end
end

p sin_deg(2)
p sin_deg(2r / 3)
p sin_deg(2.4)
p sin_deg(180)

puts
13.times{|x|
  deg = 30 * x
  p "#{deg} -> #{sin_deg(30 * x, 20)}"
}

出力結果
"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"

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.48%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Ruby

    7978questions

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