親子におすすめの新型プラネタリウムとは?

C言語を使って y=x^2-4x のyの解をニュートン法を使って求める
プログラムを作る課題を出されたんですが、ニュートン法が良く分かっていないので、いろいろ調べたり、人に聞いたりしたところ
#include<stdio.h>
#include<math.h>
void main()
{
int counter=0;
double an,g,f,sh=0.0001;
printf("初期値を入力して下さい==>");
scanf("%ld",&an);
do{
g=(an*an)/(2*an-4);
f=2*an-4;
counter++;
}while(fabs(f)>sh);
printf("反復回数 %d 回 y=%lf \n",counter,g);
}
でプログラムがこんな感じになったんですが、結局ニュートン法がどうなのかがわかりません。 なんか微分とかやるとか言われたんですが、工業系の学校で数学の授業が無いので微分についてがわかりません。
このプログラムは、コンパイルはできるんですが、動きません。
ニュートン法についてよくわからないのでどこが間違ってるかわかりません。 ニュートン法についてできるだけ分かりやすく解説してほしいです。

このQ&Aに関連する最新のQ&A

A 回答 (2件)

ニュートン法を理解するには、せめて微分の初歩の初歩は理解して下さい。


とりあえず、必要なところだけ。

y=x^2-4x
の解をもとめるには、次のようにします。
計算途中の近似解をa(n)とすると、それを元に得られる、より精度の良い近似解a(n+1)は、
a(n+1)=(a(n)*a(n))/(2*a(n)-4)
として求められます。(ニュートン法の理論から)
これを繰り返していって、
|a(n+1)-a(n)| < 0.0001
となったときに、十分精度の良い解が得られたと判断し、計算を終了します。
(計算終了の閾値0.0001は提示されたプログラムから取りました。)

プログラムの間違いは、下記の2点。
誤:scanf("%ld",&an);
正:scanf("%lf",&an);

誤:f=2*an-4;
正:f=g-an; an=g;

上記を修正し、初期値が2より大きい場合は4.000000が、初期値が2未満のときは
0.000000が求められることを確かめて下さい。
    • good
    • 1
この回答へのお礼

できました。 ありがとうございます。

お礼日時:2007/07/12 18:51
    • good
    • 1

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q方程式を2分法を用いて解くプログラム

学校で出されたCプログラムの課題で、1問だけどうしても出来ない問題があるんです。
「方程式 f(x) = x2 - 2 = 0 を 2 分法を用いて解くプログラムを作成せよ。ここで、方程式 f(x) = x2 - 2 は関数として定義せよ。上位の方から 4 桁目まで正しい値が出たらループを止めるようにする。」
というものなのですが、この「2分法」というやり方もよく分かりません。
プログラムの作成方法と併せて教えて頂けると幸いです。

Aベストアンサー

こんな感じでしょうか?

#include <stdio.h>

/* 関数 f(x) */
double f(double x) {
 return x*x-2.0;
}

/* 二分法 初期値 x1<x2 と 誤差限界 eps を入力 */
double bisec(double x1, double x2, double eps) {
 double x;
 while (x2 - x1 >= eps) {
  x = (x1+x2)/2.0; /* 中点計算 */
  if (f(x1)*f(x) > 0.0) { /* 同符号か判定 */
   x1 = x;
  } else {
   x2 = x;
  }
 }
 return (x1+x2)/2.0;
}

int main(void) {
 double eps=0.00001;
 printf("%lf %lf\n",bisec(-2,0,eps), bisec(0,2,eps));

 return 0;
}

Q3次方程式の求解プログラム(ニュートン法)について!

初心者です!
ニュートン法での3次方程式の求解プログラムを作成しようとしています。
ですがよく分かりません(-_-;)
どなたか教えていただけないでしょうか。。。

Aベストアンサー

プログラム書きました。
これで、どうでしょう?

/* 3次方程式の求解 */
#include<stdio.h>
#include<math.h>
#include<float.h>

#define PI 3.14159265358979323846

#define REAL 0 /* 実根 */
#define IMAGE 1 /* 虚数根 */

int main(void){

double a, b, c, d; /* 3次方程式の係数 */
double p, q;
double D;
double x1, x2, x3; /* 根の実部 */
double y1, y2, y3;
double Im; /* 根の虚部 */
double u, v;
double d_u, d_v;
double phi;

int kind; /* 根の種類: REAL, IMAGE */

// ここから
printf("3次方程式(ax^3+bx^2+cx+d=0)の各係数:\n");
printf("a>>>");
scanf("%lf", &a);
printf("b>>>");
scanf("%lf", &b);
printf("c>>>");
scanf("%lf", &c);
printf("d>>>");
scanf("%lf", &d);

// ここまで消して、a, b, c, d値を代入する式を書いてください。

printf("3次方程式(%gx^3%+gx^2%+gx%+g=0)の解は\n", a, b, c, d );
if( a == 0.0 ){
printf("a(%g)がゼロなので,データエラーとみなし,\n", a );
printf("解を求めずに終了します.\n");
return 1; /* 終了コードを1にして,プログラムを終了 */
}

p = ( 3*a*c - b*b ) / ( 9*a*a );
q = ( 2*b*b*b - 9*a*b*c + 27*a*a*d ) / ( 54*a*a*a );

D = q*q + p*p*p; /* Dには誤差が含まれてしまうことに注意 */

if( fabs(D) <= DBL_EPSILON ){ /* Dを数値的にゼロかどうかチェックする */
/* 3つの重根(2重根・3重根)を含む実根 */
y1 = 2*pow(-q, 1.0/3.0);
y2 = y3 = -y1/2;
kind = REAL;
}else if( D < 0 ){ /* 3つの異なる実根 */
phi = acos( -q / pow( -p*p*p, 1.0/3.0 ) );
y1 = 2*sqrt(-p)*cos(phi/3);
y2 = -2*sqrt(-p)*cos(phi/3+PI/3);
y3 = -2*sqrt(-p)*cos(phi/3-PI/3);
kind = REAL;
}else{ /* 1つの実根,2つの共役複素数の解 */
d_u = -q+sqrt(D);
d_v = -q-sqrt(D);

if( d_u >= 0 ) u = pow( d_u, 1.0/3.0 );
else u = -pow( -d_u, 1.0/3.0 );
if( d_v >= 0 ) v = pow( d_v, 1.0/3.0 );
else v = -pow( -d_v, 1.0/3.0 );
y1 = u+v;
y2 = y3 = -y1/2;
Im = sqrt(3)/2*(u-v);
kind = IMAGE;
}

x1 = y1 - b/(3*a);
x2 = y2 - b/(3*a);
x3 = y3 - b/(3*a);

if( kind == REAL ){
printf("x1=%g, x2=%g, x3=%g\n", x1, x2, x3 );
}else{
printf("x1=%g, x2=(%g + %g i), x3=(%g - %g i)\n",
x1, x2, Im, x3, Im );
}

return 0;
}

プログラム書きました。
これで、どうでしょう?

/* 3次方程式の求解 */
#include<stdio.h>
#include<math.h>
#include<float.h>

#define PI 3.14159265358979323846

#define REAL 0 /* 実根 */
#define IMAGE 1 /* 虚数根 */

int main(void){

double a, b, c, d; /* 3次方程式の係数 */
double p, q;
double D;
double x1, x2, x3; /* 根の実部 */
double y1, y2, y3;
double Im; /* 根の虚部 */
double u, v;
double d_u, d_v;
double phi;

int kind; /* 根の種類: REAL, IMA...続きを読む

Q(C言語)ニュートン法のプログラムの為の数値微分

Visual StudioでC言語のプログラムを書く課題が出されたのですが、ニュートン法のプログラムを書くために
関数f(x)=3+ 2x + {2x - cos^2(x) - sin(x)} / {x^2 + cos(x^2) + sin^3(x^3)}
という関数を微分しなければいけません。担当の先生からは、関数が複雑で普通に微分するのは難しいから
f'(x) ≒ {f(x+Δx) - f(x)} / Δx を、Δx=0.0001として数値微分しなさいと指定されています。
どのように計算すればいいのでしょうか?
Δxにそのまま代入するだけではとても計算できそうにないです。

Aベストアンサー

#include<stdio.h>
#include<math.h>

//#define MAX_ITERATIONS 50  /* ニュートン法の最大反復回数 */
#define MAXITERATIONS 50 //上だとエラーになるのでこう書き換えた

double function(double x);
double dFunction(double x);
double newtonSolver(double initValue, double tolerance);

void main(){
double x;
x = newtonSolver(4.0, 0.001); /* 1つ目の引数が初期値、2つ目は許容誤差 */
printf("function(%f) = %f\n", x, function(x)); // 0になるかのチェックだよ
}

/* ニュートン法による解の計算 */
/* initValue x の初期値 */
/* tolerane 許容誤差 */
double newtonSolver(double initValue, double tolerance){
double x = initValue; /* 初期値の代入 */
int counter; // C言語だとこうしないといけない

printf("starting Newton solver...\n");
printf("step\tx\t\tcorrection\t\n");

/* for (int counter = 0; counter < MAXITERATIONS; ++counter){ これはC++やJavaだ */
for (counter = 0; counter < MAXITERATIONS; ++counter){
/* 求める解への修正量を求める */
double correction = -function(x) / dFunction(x);
printf("%3d\t%5f\t%f\n", counter, x, correction);
x += correction;

/* 修正量(correction)の絶対値が許容誤差(tolerance)以下だったら
解となる x を返して関数を終了する
ちなみにfabs()は絶対値を求める関数 */
if (fabs(correction) < tolerance){
printf("ans = %f\n\n", x);
return x;
}
}
/* 最大反復回数を超えた場合は、収束していないので
異常値をあらわすNot a Number (NAN)を返す */
printf("Newton solver did not converge!\n\n");
return NAN;
}

/*対象の関数*/
double function(double x){
return 3 + 2*x + (2*x - pow(cos(x),2) - sin(x)) / (pow(x,2) + cos(pow(x,2)) + pow(pow(sin(x), 3),3));
}

//関数の部分はNo.3さんからのコピー(ポリポリ)
//間違っていたら、No.3さんのせいだからね~(笑)

/* 対象の関数を微分した関数 */
double dFunction(double x){
double dx;
dx = 0.0001;
return (function(x+dx)-function(x))/dx;
}



私が動かしたプログラムはこれ↑よ。
ダメならば、上のソースプログラムをコピペして、コンパイルしろ!!

計算結果は

starting Newton solver...
step x correction
0 4.000000 -6.135696
1 -2.135696 2.833077
2 0.697381 -1.283641
3 -0.586260 -0.494514
4 -1.080774 0.095784
5 -0.984990 0.014808
6 -0.970182 0.000271
ans = -0.969911

function(-0.969911) = -0.000000

です。

#include<stdio.h>
#include<math.h>

//#define MAX_ITERATIONS 50  /* ニュートン法の最大反復回数 */
#define MAXITERATIONS 50 //上だとエラーになるのでこう書き換えた

double function(double x);
double dFunction(double x);
double newtonSolver(double initValue, double tolerance);

void main(){
double x;
x = newtonSolver(4.0, 0.001); /* 1つ目の引数が初期値、2つ目は許容誤差 */
printf("function(%f) = %f\n", x, function(x)); // 0になるかのチェックだよ
}

/* ニュ...続きを読む

Qセグメンテーション違反

C言語を使用しています。

構造体に値をいれようとしたら、コンパイルは出来るのですが、実行時に
「セグメンテーション違反です (core dumped)」
となってしまい、それ以上行えません。

構造体と代入したい変数との型は、合っています。

いろいろ本などで見ましたが、何が原因かわからず困っています。
教えてください。
宜しくお願いします。

Aベストアンサー

OSは何でしょうか。コンパイラは何を使用していますか?
通常、デバッグオプションをつけて実行すると、異常の発生したソースの箇所で止まりますので、それが手がかりになります。またNo1の方が言われてますように、ソースが公開できるのであれば、ソースを提示するのが良いかと思います。

QCで3乗根を求める方法

C言語で、ある値の3乗根を求める関数はないのでしょうか?
どなたかご存知の方教えてください<(_ _)>

Aベストアンサー

精度の問題はありますが……

math.h のなかの、pow() で出来ると思いますよ。

y = pow(x, 1.0 / 3.0);

QC言語の二分法のプログラムについて

二分法によりルート2の近似値を求めるプログラム、ってどうやって作ったらいいんですか?
ちなみに初期値は2で、収束条件は10^-5です。
収束までの回数も求めなきゃいけません(ニュートン法と比較するため。ちなみにニュートン法はできました。)

似たような質問を見つけたのですが、どれも、難しいプログラムばかりで解読ができません。
関数とかif else文とかwhile文とかfor文とか、そういう簡単なのしか習ってないので、それで作れる範囲で教えてくださる方、
いらっしゃいましたら、よろしくお願いします。

Aベストアンサー

これでどうでしょう。
if文判定、及びwhile文判定を修正しました。

#include <stdio.h>
#include <math.h>
#define f(x)(x*x-2.0)
int main(void)
{
int i=0;
double m,x1=2.0,x2=1.0,eps=1.0e-5;
do{
++i;
m=(x1+x2)/2;
if (f(m)>0)
{
x1 = m;
}
else
{
x2 = m;
}
}
while (fabs(x1-x2)>eps);
printf("%f,%d\n",m,i);
return 0;
}

QCプログラミングの問題です。ニュートン法を利用して3次方程式の解を求めるプログラミング作成。

C言語のプログラミング問題です。
ニュートン法を利用して、3次方程式の解を求めるプログラムを作成しなさい。
とのことです。プログラムが得意ではないので、よろしくお願いします。

C言語のプログラミング問題で、ニュートン法を利用して次の3次方程式の解を求めるプログラミングを作成。というものなのですが、プログラミングが苦手でうまくできません。

y=ax^3+bx^2+cx+d (ただし、a>0とする)
任意の係数a,b,c,dを与え、y=0のときの解(実根のみ)を求めるプログラミングを作成せよ。


という問題です。プログラミングの内容を説明しなくてはいけないので、内容のほうも若干詳しく説明していただけると助かります。
どなたか教えてください、よろしくお願いします。

Aベストアンサー

3次方程式は複雑なので2次方程式で示します.
なんとか頑張って応用してください

前提として実数解のみとし
虚数解の場合はエラー扱いとします。

方程式は a * x ^2 * b * x + c = 0とします

判別式を実装します
CalcDという名前にします。

double CalcD(double a, double b, double c)
{
return b * b - 4 * a * c;
}

特に難しい部分はないと思います
係数から判別式を計算し、それを関数の値として戻しています

次に、方程式本体を解く部分を作ります
Resolvという名前にします

ここで難しいのはエラー(判別式 < 0)をどう扱うか?です
今回の場合、エラーつまり異常事態として扱うので
C++であれば本来、例外で教えるべきなのですが、
例外を扱うと少々難しくなりますのでやめます。

今回は解の個数を戻すことで判定させることとします
解事体は配列に入れて戻すことにします。

int Resolv(double a, double b, double c, double buffer[])
{
// 解の個数を求めます
// 判別式を関数として実装してあるので、それを使います
  double d = CalcD(a, b, c)
if (d < 0)
return 0; // 実数解はありません

  if (d == 0)
{
buffer[0] = -b / (2 * a);
return 1; // 重解です
}
 else
{
buffer[0] = (-b + sqrt(d)) / (2 * a);
buffer[1] = (-b - sqrt(d)) / (2 * a);
return 2; // 相異なる2つの実数解です
}
}

あとはプログラム全体を制御する部分です
しかし、もう部品はありますのであとは簡単です

int main(int argc, char *argv[])
{
// エラーチェックは省略します
 // 本来はパラメータの妥当性を検証すべきです

 double a = atof(argv[0]);
 double b = atof(argv[1]);
 double c = atof(argv[2]);

// 実際に計算します
 double buffer[2];
int n = Resolv(a, b, c, buffer);

// 結果を表示します
 switch (n)
{
case 0:
printf("実数解はありません。");
break;

case 1:
printf("実数解は %f です.", buffer[0]);
break;

default:
printf("実数解は %f と %fです.", buffer[0], buffer[1]);
}

return 0;
}

如何でしょうか?
プログラムの作成の雰囲気のようなものがつかめたでしょうか?
とにかく、分かり易い単位に関数を作ることが大切です。
関数へのパラメータの渡し方
関数からの情報の戻し方(戻り値を使う方法、アドレス渡し(配列もアドレス渡しです)等のテクニックを伝えたつもりです
これを参考に3次方程式も頑張ってください

3次方程式は複雑なので2次方程式で示します.
なんとか頑張って応用してください

前提として実数解のみとし
虚数解の場合はエラー扱いとします。

方程式は a * x ^2 * b * x + c = 0とします

判別式を実装します
CalcDという名前にします。

double CalcD(double a, double b, double c)
{
return b * b - 4 * a * c;
}

特に難しい部分はないと思います
係数から判別式を計算し、それを関数の値として戻しています

次に、方程式本体を解く部分を作ります
Resolvという名前にします...続きを読む

QC言語のプログラムが実行できません。

C言語のプログラムが実行できません。

コンパイルは出来るんですが、実行すると、「Segmentation fault」と表示されてしまいます。

これは何のエラーなんでしょうか?
基本的な事かもしれませんが、分かる方宜しくお願い致します。

Aベストアンサー

僕も何度も出したなぁ。

ひとくちにSegmentation faultといっても、それこそさまざまな要因があるので、
これだけで原因を突き止めるのは非常に難しいです。

コンパイルはあくまで文法としてみているだけであり、
処理の流れ、メモリ確保など、プログラムそのものを見ているわけではありません。
このエラーが出るのは文法などよりもっと上位の原因なのです。
たとえばですが。
長さ10の配列があったとして、11番目以降を参照したりすると、
そういうのが出たような気がします。

ですから、変数があれば、その内容をprintf文で逐一出していき、
変な値が入っていないとか、少しずつ直していくしかないと思います。

Q三角関数の記述の仕方

タイトルそのまんまなんですが、三角関数はC言語ではどのように記述すればいいでしょうか?
角度にラジアン表記でπ(パイ)を使いたいんですが、その表記方法もわかりません。
僕の持っている本に載ってなかったので質問させていただきました。
よろしくお願いします。

Aベストアンサー

C言語で三角関数を使うためには、math.h をインクルードする必要があります。使い方は例えば、こんな感じです。

#define M_PI 3.14159265358979 /* 円周率 */

double x, y, theta;

theta = M_PI / 4.0;
x = cos(theta); /* sin,cos,tanの引数は弧度法の角度です。*/
y = sin(theta);

πは上記の例のように自分で定義して使ってください。

QC言語、行列の積を求めるプログラムについて

「次に示す行列x,yの積を求めるプログラムを作成せよ。
  x[2][3]={{1,2,3},{4,5,6}} y=[3][2]={{1,5},{5,3},{81}}」
という問題です。自分ではとりあえず、
#include<stdio.h>
int main(void)
{
int i,j;
int x[2][3]={{1,2,3},{4,5,6}};
int y[3][2]={{1,5},{5,3},{8,1}};
int xy[3][3]={0};

for(i=0;i<3;i++)
for(j=0;j<3;j++)
xy[i][j]=x[i][j]*y[i][j];

for(i=0;i<3;i++){
for(j=0;j<3;j++)
printf("%3d",xy[i][j]);
putchar('\n');
}
return 0;
}
というプログラムを作ってみましたが、ダメでした。
ちゃんと積の表示が出るようにするにはどこをどう変えるべきでしょうか?

Aベストアンサー

#include<stdio.h>
int main(void)
{
int x[2][3] = { { 1, 2, 3 }, { 4, 5, 6} };
int y[3][2] = { { 1, 5 }, { 5, 3 }, { 8, 1 } };
int xy[2][2];
int i, j, k;

for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
xy[i][j] = 0;
for (k = 0; k < 3; k++) {
xy[i][j] += x[i][k] * y[k][j];
}
}
}

for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
printf("%4d", xy[i][j]);
}
putchar('\n');
}
return 0;
}

#include<stdio.h>
int main(void)
{
int x[2][3] = { { 1, 2, 3 }, { 4, 5, 6} };
int y[3][2] = { { 1, 5 }, { 5, 3 }, { 8, 1 } };
int xy[2][2];
int i, j, k;

for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
xy[i][j] = 0;
for (k = 0; k < 3; k++) {
xy[i][j] += x[i][k] * y[k][j];
}
}
}

for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
printf("%4d", xy[...続きを読む


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング