![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
sinxの数値計算
任意のxに対するsinxの値をマクローリン展開を利用して近似し、誤差の限界(n番目の値が1*10^-8)になるまでもとめよ。
という問題なんですが、for文でいろいろやってみたのですが、n番目の値が1*10^-8までというのがどうしてもできません。
C言語です。
たぶん、階乗の部分が間違ってると思われます。
下のが自分で考えたものです。アドバイスいただけたら嬉しいです。
#include <stdio.h>
int main(void)
{
signed int i,v;
double x=-1;
double a,m,n=1.0;
double sinx = 0.0;
a=x;
v=1;
printf("a=%f\n",a);
printf("sinx = %f\n",sinx);
while(1)
{
sinx = sinx + a;
m=x;
m=m*x;
a = (-1)*v*m/((n+1)*(n+2));
n=n+2;
v=v*(-1);
if ((a < 1e-8) && (a > -1e-8)) break;
}
printf("sinx = %f",sinx);
return (0);
}
No.2ベストアンサー
- 回答日時:
#include <stdio.h>
/*#include <math.h>*/ /*検算用に使うsin(x)用。検算が必要ならコメントを外す*/
int main(void)
{
int n,v;
double a,k,l,xx;
double x;
double sinx;
printf("sin(x)のxを入力:");
scanf("%lf",&x);
/*誤差の限界は「10の-8乗」なので精度を「8桁」に指定*/
/*printf("sin = %.8f\n",sin(x));*/ /*検算用にライブラリ関数でのsin(x)を表示。検算が必要ならコメントを外す*/
/*変数の初期化*/
sinx = 0.0;
n = 1; /*2n+1。1,3,5,7…と増加*/
v = 1; /*加算か減算かのフラグ。1,0,1,0,1,0…と変化*/
k = 1.0; /*(2n+1)!。最初は1!なので1*/
l = x; /*xの(2n+1)乗。最初はxの1乗なのでx*/
xx = x * x; /*xの1乗にxの2乗を掛け、xの3乗、5乗、7乗…を作る為に用意した「xの2乗」*/
while(1)
{
a = (1.0 / k) * l; /*赤枠の部分式*/
if (v) sinx += a; /*nが1,5,9…なら加算*/
else sinx -= a; /*nが3,7,11…なら減算*/
n += 2; /*nを2づつ加算*/
k *= (n - 1) * n; /*(2n+1)!を計算*/
l *= xx; /*xの(2n+1)乗を計算*/
v = !v; /*加算と減算の入れ替え*/
/*誤差の限界判定はsinxにaを加減算した後で行う*/
/*そうしないとxが3.1415926535の時に結果が*/
/*ライブラリのsin関数と食い違ってしまう*/
if ((a > -1e-8) && (a < 1e-8)) break; /*誤差の限界*/
}
/*誤差の限界は「10の-8乗」なので精度を「8桁」に指定*/
printf("sinx = %.8f",sinx); /*結果を表示*/
return (0);
}
No.4
- 回答日時:
もう一度失礼します。
少しの間違いを除けば基本的に質問者さんのコードであっているし、
そちらのほうがセンスがいいので、それをもとにしたほうがベターです。
質問者さんはわかっているはずなので念のためですが、サインの展開式
sin x = Σ[m=0,∞] (-1)^m x^{2m+1}/(2m+1) ! = Σ[m=0,∞] a(m)
から
a(m) = (-1)^m x^{2m+1}/(2m+1) !
= (-1)^(m-1) x^{2(m-1)+1}/(2(m-1)+1) ! × (-1)x^2/[(2m)(2m+1)]
= a(m-1) × (-1)x^2/[(2m)(2m+1)]
これを利用したアルゴリズムです。
こんなかんじですね。
sx=0.0;
a=x;
n=1;
printf("sin(%lf) = %.8lf\n", xin, sin(x));
printf("----------------------------------------------\n");
do {
sx += a;
printf("%3d: sin(%lf) = %.8lf, a(%d)=%le\n", n, x, sx, n, a);
a = a*(-1)*x*x/(n+1)/(n+2);
n+=2;
} while(fabs(a)>1e-8);
printf("----------------------------------------------\n");
printf("a(%d)=%le\n", n, a);
xが大きな数になるとオーバーフローするので、
0<x<2πになるように前処理はしておいたほうがいいと思います。
![](http://oshiete.xgoo.jp/images/v2/common/profile/M/noimageicon_setting_14.png?e8efa67)
No.3
- 回答日時:
以下のようにして下さい。
-----------------------
#include <stdio.h>
// xのn乗を求める
double mypow(double x,int n)
{
int i;
double ans = x;
for (i = 1; i < n; i++){
ans *= x;
}
return ans;
}
// nの階乗を求める
double myfact(int n)
{
if (n == 1) return 1.0;
return (myfact(n-1) * (double)n);
}
int main(void)
{
int i;
int fugou = 1;
double x=-1;
double v,absv;
double sinx = 0.0;
printf("x=%f\n",x);
printf("sinx = %f\n",sinx);
for (i = 1; ; i += 2){
// xのi乗 / iの階乗 を求める
v = mypow(x,i) / myfact(i);
// 誤差の10の-8乗未満なら終了
//一旦、絶対値を求め、絶対値で判断する(その方がわかりやすい)
absv = v;
if (absv < 0.0) absv *= (-1.0); //負なら正にする(絶対値にする)
if (absv < 1.0e-8) break; //絶対値で比較
sinx += (v*fugou);
fugou *= (-1); //iが3,7,11...の時は引き算なのでマイナスにする
}
printf("sinx = %f\n",sinx);
return (0);
}
-----------------------
No.1
- 回答日時:
>a = (-1)*v*m/((n+1)*(n+2));
は
a = a*(-1)*x*x/(n+1)/(n+2);
(Cらしく書けば a *= (-1)*x*x/(n+1)/(n+2);)
です。n-2の時のaを掛け忘れています。変数v,mは不要ですが、
少しでも演算速度をあげるならm=x*xを【ループの外】に書いてx*xをmに置き換える。
nは整数のほうがいいでしょう。
>v=v*(-1);
で符号を変えた後、もう一度a=(-1)*・・・で-1を掛けているので、結局符号は変わっていませんね。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# C言語のマクローリン展開ローラン展開のコードについて 3 2022/12/15 14:45
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- 数学 数学トリック!間違ってるところを指摘してください。 「問題。sinx+2/sinxの最小値を求めよ。 3 2022/09/21 10:52
- C言語・C++・C# c言語でユーザ関数を利用して複素数のべき乗と絶対値の数列を計算するプログラムが作りたいです。 3 2023/01/29 22:13
- C言語・C++・C# Cのdoubleの浮動小数点表示について 3 2023/04/17 13:14
- C言語・C++・C# C 言語の Gauss Jordan 法について 2 2022/12/28 11:16
- C言語・C++・C# バイナリファイルをコピーするのにかかる時間を測りたいのですが実行するとFatel error:gli 2 2022/11/03 01:10
- C言語・C++・C# (C言語)めちゃくちゃな値になってしまいます。 5 2022/08/13 11:55
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ボール同士の衝突
-
プログラムでの数字につく”f”の...
-
c言語で、繰り返し文の中で、0....
-
関数におけるif文とreturn文に...
-
C言語の複素数についてです。
-
float?数字の後にLがつくもの
-
三角関数のグラフ
-
C言語 関数プロトタイプ宣言の...
-
C言語で-23乗を取り扱うには
-
c言語について 下記の計算結果...
-
プログラムの実行時に'<'でリダ...
-
信頼区間の1.96や1.65ってどこ...
-
複数桁10進数の*桁目だけを抽出...
-
数学 確率変数Xは、X=2またはX...
-
Enterキーを押されたら次の処理...
-
反転した数値を表示させるやり方
-
2÷3などの余りについて
-
中学生で数学です。 √84nが自然...
-
「Aに対するBの割合」と「Aに対...
-
std::set<int> で、ある値が何...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
doubleの変数にintとintの割り...
-
float型とdouble型の変数の違い...
-
c言語で、繰り返し文の中で、0....
-
C言語を実行すると-infが出てき...
-
C言語 関数プロトタイプ宣言の...
-
C 開放してるのにエラー(doubl...
-
C言語の型による処理速度の違い
-
至急です! マクロ定義で #defi...
-
関数におけるif文とreturn文に...
-
c言語のプログラミングについて...
-
2分法で方程式の複数の解を自...
-
-1.#IND00と出てしまうのですが...
-
doubleは常に%lfとするべきなのか
-
C言語のpow関数の不具合
-
C言語で-23乗を取り扱うには
-
C言語で台形公式を使った二重積...
-
Cで3乗根を求める方法
-
sin(x)の近似について
-
2次方程式の解を求めるプログ...
おすすめ情報