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にそのまま代入するだけではとても計算できそうにないです。
No.1
- 回答日時:
そのf(x)が
f:3+ 2*x + (2*x - cos(x)^2 - sin(x)) / (x^2 + cos(x^2) + sin(x^3)^3);
と同じであるなら、計算ソフトで微分できるようです。
(%i3) f:(-sin(x)-cos(x)^2+2*x)/(sin(x^3)^3+cos(x^2)+x^2)+2*x+3
(%i4) diff(f,x)
(%o4) (2*cos(x)*sin(x)-cos(x)+2)/(sin(x^3)^3+cos(x^2)+x^2)
-(-sin(x)-cos(x)^2+2*x)*(9*x^2*cos(x^3)*sin(x^3)^2-2*x*sin(x^2)+2*x)/(sin(x^3)^3+cos(x^2)+x^2)^2+2
よって一般解は上ですが、先生が要求しているのは、特定の場所での微分値を求める作業だと思います。その特定の場所は何処ですか。
No.2
- 回答日時:
こんばんは。
double f(double x) {
return 問題の関数;
}
とおけば
df = (f(x+h)-f(x))/h
で数値微分できるでしょっ。
ここでh = Δx = 0.0001
h = 0.0001;
x = 何か適当な値;
while(1) {
df = (f(x+h)-f(x))/h; //ここが数値微分
xn = x - f(x)/df;
if (収束条件) break;
x = xn; //xの更新
}
で、お求めのニュートン法の本体部分が出来上がり。
dfが0になる場合の例外処理などが必要になりますけれども、これで計算できるはず。
df = f'(x)
ね。
先生は、こういう風に計算をしなさいとおっしゃている。
不安ならば、反復制限を入れる。
whili文の前に
n = 0;
を入れて、
while (++n < 100)
とか
while(n++ < 100)
とかすればよい。
このあたりは好みがあるので、while文ではなく
for(n = 0; n < 100; n++)
でも何でもいいです。
do while文を使ってもいい。
一般的にニュートン法は収束が速いから、10回も反復させれば所定精度の数値解は求まると思いますけれど。
No.3
- 回答日時:
No.2さんの回答を見ると、その場所はプログラム中で指定しても良いようですね。
その場所をx1として、作って見ました。
環境は
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
です。
これはVisual Studio 2008 Express Editionのコマンドライン版です。
<x.c>
#include <stdio.h>
#include <math.h>
float f(double x) {
return x*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));
}
void main() {
double x1 = 3;
double dx = 0.00001;
printf("%f\n", (f(x1+dx) - f(x1))/dx);
}
コンパイルは、パスの通った場所で
C:>cl x.c
x.exeを実行すると、次の結果。
6.008148
一般的にはf(x)=x^2として、f'(3)=2x=2*3=6。
No.4
- 回答日時:
/*対象の関数*/
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 (f(x+dx)-f(x))/dx;
}
でいいんじゃない。
No.5
- 回答日時:
あっ、ゴメン、ゴメン。
NO.4の回答にはウソがあります。
/*対象の関数*/
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;
}
です。
No.6
- 回答日時:
補足にあったプログラムに、No.5
のプログラムをくっつけコンパイルして、実行させたよ。
私のCコンパイラーはGCCなんで多少の修正をする必要があった。
───このプログラムのC言語は、CじゃなくC++が混じってる!!───
実行結果は
starting Newton solver...
step x correction
ans = -0.969911
となるようでございます。
No.7
- 回答日時:
☆ただ、この関数の解は、-0.559629になるらしいのですが、どこが間違っていると思われますか?
もしかしたら、sin^3(x^3)の部分なのでしょうか?
◇どこが違いますかといわれましても、
ソースプログラムを見せていただかないことには、
何とも言えませんよ(ニコニコ)。
たぶん、
対象の関数、対象の関数を微分した関数
のどこかを書き間違えているんでしょうね。
ですから、
コピペですよ、コピペ。
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));
と
double dx;
dx = 0.0001;
return (function(x+dx)-function(x))/dx;
をコピーして、プログラムに貼り付ける。
何を隠そう、
オレもこの質問文にあるプログラムをコピペしただけだし(ポリポリ)。
質問者さんが補足に書いたプログラムと、おれが書いた部分もコピペした奴をコンパイル、実行しただけだもん(笑)。
そうすると、
ans = -0.969911
になるはずですよ。
この時、
function(-0.969911)がほとんどゼロになることも確かめてあります。
うまくいかなかったら、また連絡してください。
No.8ベストアンサー
- 回答日時:
#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
です。
No.9
- 回答日時:
No.1です。
NemurinekoNyaさんが複数回返答されてますね。
>この関数の解は、-0.559629になるらしいのですが、
は、どの場所での微分値でしょうか。
例えば、x=3での、与えられた条件の微分値は以下です。
f:3+ 2*x + (2*x - cos(x)^2 - sin(x)) / (x^2 + cos(x^2) + sin(x^3)^3);
define(F(x),f);
x1:3$
dx:0.0001$
(F(x1+dx)-F(x1))/dx, numer;
(%i3) f:(-sin(x)-cos(x)^2+2*x)/(sin(x^3)^3+cos(x^2)+x^2)+2*x+3
(%i4) define(F(x),f)
(%i5) x1:3
(%i6) dx:1.0E-4
(%i7) ev((F(dx+x1)-F(x1))/dx,numer)
(%o7) 3.407411997962129
上はMaximaでの実行例です。
MaximaにC形式の数式を出力する機能は、私の知りうる範囲では、ありません。
Fortranならあります。以下です。
(%i4) fortran(f)
(-sin(x)-cos(x)**2+2*x)/(sin(x**3)**3+cos(x**2)+x**2)+2*x+3
上のfが
>関数f(x)=3+ 2x + {2x - cos^2(x) - sin(x)} / {x^2 + cos(x^2) + sin^3(x^3)}
と一致しているかどうかを確認して下さい。
そして、その-0.559629がどの場所でのxなのか教えて下さい。
なお、pow()はCライブラリmath.h中にあります。貴方のCコンパイラでのpowの定義を教えて下さい。
No.10
- 回答日時:
C系のコンピュータ言語では
a^3 = pow(a,3)
という風に書くんですよ。
a^n = pow(a,n)
ね。
ただ、文法にうるさいCコンパイラだと、
pow(a,b)
のa、bのデータの型が実数でなければならないので、bに整数型のデータを入れるとエラーにされてしまう。
BorlandのCコンパイラーなどがその代表。
難しく考えないで、
この質問ページにある
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));
をドラッグ&ドロップし、コピーして、ソースプログラムの問題箇所に貼り付ければいいんですよ。
ドラッグ&ドロップ
http://www.pc-master.jp/words/drag-drop.html
コピー&ペースト
http://siriasu.s10.xrea.com/etc/copipe.htm
それで動くと思うんだけれどな。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 数学 次の関数を微分せよ y=sin^4 x cos^4 x という問題で自分は積の微分法で微分して y' 3 2023/05/17 20:38
- 数学 数学IIについて質問です 関数f(x)=x^3+2x^2-2について、x=2における微分係数は【?? 3 2022/09/11 20:29
- 数学 テーマ122が成り立つのは普通にやっても合成関数の微分法を利用してもできるのはわかるんですが。 25 1 2022/07/14 02:53
- 数学 『Cの微分.2』 3 2023/02/15 19:47
- 数学 以下の議論はどこがおかしいのでしょうか? また、それをどう直せばよいのでしょうか? 教えて下さい。よ 6 2022/05/04 15:42
- 数学 関数の極値と微分係数の関係について 6 2023/04/23 14:35
- 数学 微分(全微分)についての質問です。 2 2022/04/07 17:08
- 数学 数学微分方程式の問題です。次に書く問題を教えて欲しいです。質量mの物体が自然長l、ばね定数kのバネで 1 2022/04/29 21:23
- 数学 数学3の微分法・対数関数の導関数に関しての質問です。 [ ] は絶対値を表しています。 y=log[ 3 2022/05/24 14:07
- 数学 x=r・cosθの2回微分 θ=ωtとすると? 5 2022/05/10 23:53
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
C 開放してるのにエラー(doubl...
-
C言語 関数プロトタイプ宣言の...
-
数値を指数部と仮数部に分離したい
-
学校の課題で2次方程式のプログ...
-
関数におけるif文とreturn文に...
-
C言語を実行すると-infが出てき...
-
float型とdouble型の変数の違い...
-
C言語で表記についの質問です
-
指数の表示
-
2分法で方程式の複数の解を自...
-
doubleは常に%lfとするべきなのか
-
物体が往復する動きを作りたい
-
C言語で内積、、、わかりません。
-
c言語のコンパイルエラー canno...
-
C言語のpow関数の不具合
-
処理時間計測
-
float?数字の後にLがつくもの
-
「割り算」 と 「分数の掛け算」
-
C++標準ライブラリィーのcomple...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
プログラムでの数字につく”f”の...
-
float型とdouble型の変数の違い...
-
doubleの変数にintとintの割り...
-
C言語を実行すると-infが出てき...
-
C 開放してるのにエラー(doubl...
-
至急です! マクロ定義で #defi...
-
c言語で、繰り返し文の中で、0....
-
関数におけるif文とreturn文に...
-
C言語 関数プロトタイプ宣言の...
-
C言語初心者 構造体 課題について
-
C言語の型による処理速度の違い
-
Cで3乗根を求める方法
-
C言語で-23乗を取り扱うには
-
2分法で方程式の複数の解を自...
-
doubleは常に%lfとするべきなのか
-
c言語のコンパイルエラー canno...
-
C言語で直角三角形の斜辺を求め...
-
C言語のプログラムで#include<m...
-
int とdoubleの比較
-
C++で外積
おすすめ情報
説明不足なばかりにお手数おかけしてしまって本当に申し訳ありません。
実は、こんなプログラムを改変して作成しろ、と言われていまして・・・
文字数がオーバーしてしまったので画像を貼らせていただきます。
すみません、画像が元々のサイズより小さく表示されて見づらくなってしまいましたので、プログラムを書かせていただきます。
#include<stdio.h>
#include<math.h>
#define MAX_ITERATIONS 50 /* ニュートン法の最大反復回数 */
double function(double x);
double dFunction(double x);
double newtonSolver(double initValue, double tolerance);
void main(){
newtonSolver(4.0, 0.001); /* 1つ目の引数が初期値、2つ目は許容誤差 */
}
/* ニュートン法による解の計算 */
/* initValue x の初期値 */
/* tolerane 許容誤差 */
double newtonSolver(double initValue, double tolerance){
double x = initValue; /* 初期値の代入 */
printf("starting Newton solver...\n");
printf("step\tx\t\tcorrection\t\n");
for (int counter = 0; counter < MAX_ITERATIONS; ++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 0;
}
/* 対象の関数を微分した関数 */
double dFunction(double x){
return 0;
}
このようなプログラムです。この「対象の関数」と「対象の関数を微分した関数」をなんとかして編集しなければいけないんだろうは思っているのですが、どうすればいいのでしょうか?本当に申し訳ありませんがよろしくお願いします。
おかげさまでプログラムを走らせることができました。本当にありがとうございます。
ただ、この関数の解は、-0.559629になるらしいのですが、どこが間違っていると思われますか?
もしかしたら、sin^3(x^3)の部分なのでしょうか?
すみません、プログラミングは大の苦手で、質問の意味が正しく理解できていないかもしれませんが、一応返答させていただきます。
解がどの場所での微分値なのかとのことですが、恐らく初期値、x=4ではないかと思います。
あと、powの定義というのはちょっと分からないです。申し訳ありません。
関数f(x)=3+ 2x + {2x - cos^2(x) - sin(x)} / {x^2 + cos(x^2) + sin^3(x^3)}が間違いで、正しいのは
関数f(x)=3+ 2x + {2x - cos^2(x) + sin(x)} / {x^2 + cos(x^2) + sin^3(x^3)}でした。そのせいで答えが大きく違ってしまったようです。
あとは/*対象の関数*/
double function(double x){
double a = pow(x, 2);
double b = pow(x, 3);
return 3 + 2 * x + (2 * x - pow(cos(x), 2) + sin(x)) / (pow(x, 2) + cos(a) + pow(sin(b),3));
}
で、解が-0.559629となりました。
お二方にはご迷惑をおかけしました・・・
これを機に、少しプログラミングの勉強をしようと思います。本当に助かりました。ありがとうございます。