• ベストアンサー

c言語の関数定義について

次の関数定義を考える. int f(int x) {if (x > 0) {return x * f(x-1);} else {return 1;} } この関数f と働き(すなわち,引数と戻り値の関係)が同じで再帰呼出(recursive call) を使わない関数g をC で定義せよ.ただし,オーバーフロー(overflow) については考慮しなくてよい. ”この関数f と働き(すなわち,引数と戻り値の関係)が同じで再帰呼出(recursive call) を使わない関数g をC で定義せよ”って理解できません、どのように定義したいいか、ご教授お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8518/19364)
回答No.4

とゆ訳で、題意に沿った解答は int g(int x) {  int ans;  int i;  ans = 1;  for (i = 2;i <= x;i++) {   ans *= i;  }  return ans; } ここで、xが2未満(1と0以下、つまり1以下)の時は、forループを回らない事に注意しましょう。 ループを回らない場合、1で初期化したansがそのまま「関数の戻り値」になりますので、1以下の引数を与えられた場合は常に1を返します。 また、元のf()関数は「0より大きい、つまり、1以上ならばx * f(x-1)を、1未満なら1を返す」としていますが、上記のプログラムは「1より大きい、つまり2以上ならばループを回る」となっていて、判断数値が微妙に違います。 これは f(引数xが2以上)→1~xまでの掛け算の答えを返す f(引数xが1)→1 * f(0)、すなわち、1 * 1、結局は1を返す f(引数xが0以下)→1を返す となっていて「f(1)は1を返すんだから、f(0以下)と同じ処理をしても構わない」というのが理由です。 つまり「0以下なら1を返す」のと「1以下なら1を返す」のは、結果が同じになるって言うのが理由です。 試しに、元の関数f()をちょっと改造してf2()関数を作って int f2(int x) {if (x > 1) {return x * f2(x-1);} else {return 1;} } としても、判断数値が違うにも関わらず、関数f()とまったく同じ働きをします。 蛇足ですが、私なら int f3(int x) {return (x > 1) ? x * f3(x-1) : 1;} と書きます。

takahasi77
質問者

お礼

詳しく教えていただいて、どうもありがとうございます。

その他の回答 (4)

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.5

テスト用main関数付き #include <stdio.h> int f(int x) { if (x > 0) { return x * f(x-1); } else { return 1; } } int g(int x) { int ans = 1; while (x > 0) { ans *= x--; } return ans; } int main(void) { int valid, i; for (valid = 1, i = -1; i <= 10; i++) { int a = f(i), b = g(i); printf("%2d:%10d%10d\n", i, a, b); if (a != b) { valid = 0; } } printf("\nf()とg()は等価と見なせま%s。\n", valid ? "す" : "せん"); return 0; }

takahasi77
質問者

お礼

詳しく教えていただいて、どうもありがとうございます。

  • chie65535
  • ベストアンサー率43% (8518/19364)
回答No.3

>”この関数f と働き(すなわち,引数と戻り値の関係)が同じで再帰呼出(recursive call) を使わない関数g をC で定義せよ”って理解できません >どのように定義したいいか、ご教授お願いします。 Cでは「関数を定義する」とは「関数を作る」って意味です。 要は「再帰を使わないで、同じ仕様の関数を作れ」って事。 >このようにして、ただしいですか? >int g(int x) >{ >int sum=x; >while(--x) >sum*=x; >return sum; >} 残念ながら、私が教授なら評価は「不可」です。 「f(0)」や「f(-1)」は、1を返しますが、質問者さんの関数はそうなっていません。 「同じ働きをしていない。引数に0や負数を入れると結果が異なる。題意に沿った解答ではないので、評価は不可」です。

takahasi77
質問者

お礼

詳しく教えていただいて、どうもありがとうございます

  • asuncion
  • ベストアンサー率33% (2126/6288)
回答No.2

関数fとgに同じ引数を与えたときに同じ結果を得れば、 題意に沿った関数gを定義できたと見なせるでしょう。 何かの「合計ではない」のにsumという名前を付けるのはどうなんだろう?というのはありますけれど…。

takahasi77
質問者

お礼

asuncionさん、了解しました。どうもありがとうございます。

  • NNori
  • ベストアンサー率22% (377/1669)
回答No.1

たとえば、f(10) は何を返すかわかりますか? 10は 0より大きいので、 10 * f(9) を返しますよね? f(9) は 9 * f(8) です。 f(8) は 8 * f(7) です。 ... f(0) は x>0 を満たさないので 1 を返します。 つまり、 f(10) = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1 * 1 となります。 こんな答えを返すようにプログラムしなさい!っていう意味です。

takahasi77
質問者

お礼

NNoriさん、詳しく教えていただいて、どうもありがとうございます。このようにして、ただしいですか? int g(int x) { int sum=x; while(--x) sum*=x; return sum; }

関連するQ&A

  • C言語の関数について。

    学校の課題がわからないので教えてください。 1. 次の関数recfunc()は関数内で自分自身を呼び出す再起関数である。 int recfunc(int x){ if(x<=0)return -1; else if(x==1) return 3; else return 3*recfunc(x-1)-2; } 引数に1,2,3,4,5,...を与えたときの返り値を求めよ。その結果から、一般に 整数値nが与えられたとき、どのような値が計算されるか推測せよ。 一体何を返す関数だろうか?またどのようにその計算が実現されているか を簡潔に述べよ。 2.どのような再帰関数も、再帰を用いない関数に書き換えることができる。 問題1の関数recfunc()と同じ引数、同じ返り値をもつ再帰を用いない関数 func()を作成せよ。 2問も質問してすみません。 このプログラミングのレポートを提出しなくてはならないので困ってます。 何卒よろしくお願いします。

  • C言語(引数)

    はじめまして。 C言語を習い始めたものです。 関数を定義するとき、よく耳にする、仮引数や実引数があると思います。 仮引数は関数の定義内で値をうけとる変数のことであり 実引数は関数を呼び出す際に渡す値を実引数というらしいのですが どこからどこまでを仮引数と呼ぶのかわかりません。 例えば、 fの関数の定義内で ↓があるとします。 (関数にする意味はないのですが、確認のためあしからず・・・) double f(double x) {     x=5;     return(x); } この場合、仮引数とよばれるものは double f(double x)の xが仮引数であって x=5;のxは仮引数と呼ばないのでしょうか?? もしそうならば void f(double x) { printf("%f",x); } のprintf("%f",x);内のxは仮引数とよぶのでしょうか? 質問の内容が意味不明かもしれませんが よろしくお願いします。

  • 関数の戻り値に関数のアドレスを返すできませんか?

    戻り値に関数のアドレスを与える方法が良く分かりません. ひとまず,以下のように動くプログラムを作りたいと思っています.  f2(1,2)(1); //このように引数の()を二種類に分けたいのですが 無理でしょうか?? プログラムは下のように作って実験しているのですが良く分かりません・・ どなたか分かる方居たら教えてください. int f1(int x , int y){ return 0; } ????? int ff(int x){ return f; };

  • お願いします

    int c(int x)    { x = x + 3;     { int t; t = 6;      { int x; x = 6; t = x + t + 12; }    return x + t;    } } 上の関数の変数の名前替えだけが許されるという条件の下で,関数f の働き(すなわち,引数と戻り値の関係)を変えずに,上記の関数定義の4行目 { int x; x = 6; t = x + t + 12; } の(int x)を(int t) に変更して.必要最小限の変数の名前替えを施した関数定義を書け. 私はこのように定義していますので、正しいですか、「関数の変数の名前替えだけが許されるという条件の下で,関数f の働き(すなわち,引数と戻り値の関係)を変えずに」ってあまり理解できてないので、ご教授お願いいたします。 int c(int x)    { x = x + 3;     { int y; y = 6;      { int t; t = 6; y = t + y + 12; }    return x + y;    } } }

  • 関数の定義

    関数の定義とは ここから 戻り値の型 関数名(引数リスト) {   文;   ・・・   return式; } ここまで のことをいうのでしょうか??あたりまのような質問ですみません。 参考書には、「関数の定義はブロック内にまとめて記述します」 となっているので{ }の中のものだけなのかと思ってしまいました。 初歩的な質問ですがよろしくお願いします。

  • C言語プログラム能力検定の問題でわからないところがあります

    今度C言語プログラム能力検定を受けるのですが、過去問の回答ではわからず質問させてもらってます(以下ソース) ------------------------------------------ #include<stdio.h> int mod(int a, int b); int d, f = 10; main() { int a,b,c; enum cl {g,h} a=12; b=5; c=mod(a,b); a++; ++b; c=mod(a,b); printf("c=%d\n",c); ←(1) } int mod(int b, int a) { int c; c=b/a; c=b-c*a; return(c); } -------------------------------------------------- 問題は(1)はどのように出力されるでしょう?といったもので、 答え(出力結果)は「1」でした。回答の説明によると 「変数cはmain関数内で宣言され、mod関数の戻り値が格納される。 mod関数の戻り値は二つの引数の剰余であり、ここでは2回目のmod関数 の戻り値が表示される。2回目の仮引数は、aが6で、bが13で戻り値は1になる」 ということでしたが>mod関数の戻り値は二つの引数の剰余であり… というのがよくわかりません…剰余算というのは「%」のことですよね? であれば「c= a % b」といった記述がでてくれば13÷6=2…1で「1」となり、理解できるのですが、それらしき記述がないので(--;) どなたか教えていただけないでしょうか? よろしくおねがいします。

  • C言語の高階関数についてです。

    C言語の高階関数についてです。 double f ( (*g)(double) ){...} とすると「関数を引数にする関数」が作れますが、 「関数を引数にする関数」を引数にする関数って作れますか??? その場合は、引数のところどうやって書けばいいでしょうか??

  • C言語のreturnの使い方

    return a, b; のように2つの引数で値を返せることを最近になり 知りました。ところで以下のような使い方は可能でしょうか? test( , )という2つの引数が必要な関数にnum()で return 1,2としてひとつの関数呼び出しで引数2個分に すると言うようなことです。 #include <stdio.h> int test( int i, int j){   printf("%d %d",i,j); } int num(void){   return 1,2; } int main(void){   test( num() ); }

  • nCrの計算

    nCrの計算のプログラムを nCr=n!/(r!(n-r)!) を用いて再帰的関数を使って書いたのですが、もし nCr=n(n-1)(n-2)・・・(n-r+1)/r! であることを用いて、nからmまでの掛算を実現する2引数の関数を定義して、再帰的関数呼び出しを用いたnCrのプログラムを作成するとしたらどうなるでしょうか。 関数x!の定義は、関数の宣言をlong factorial(int x)として、 if (x==0) return(1); else return(x*factorial(x-1)); となることは分かるのですが、 2引数の関数m(m+1)・・・nはどう作れば良いのか全くわからないので、プログラムが書けない状態です。アドバイスお願いします。

  • C言語によるガンマ関数の記述

    今、C言語を用いてガンマ関数を計算する方法を模索中でです。 理想的にはガンマ関数の引数に数値を入れたら戻り値を返すというのがいいのですがそうもうまくいかないと思います。 そこで以下のような形で整数の場合と非整数の場合で作ることを考えています。しかし、引数が整数のときはわかるのですが、非整数のときがわかりません。どうしたらよいでしょうか。 以下に関数の概要を掲載します。 ==========関数の概要=========== 関数名:Gamma(x) 戻り値:double 引数:x[double] 1)引数が0より大きい整数(1,2,3...)のとき   階乗の自己回帰文を使用して計算 2)引数が0より大きい非整数の場合 ==========▲ここまで==========

専門家に質問してみよう