• ベストアンサー

足し算と引き算だけでつくる演算

半分数学の問題なのですが、考え方はプログラミングなのでこちらのカテゴリで質問しました。 大学で計算の可能性という講義を受けています。 この講義ではwhileプログラムというプログラムを使って計算の可能性を調べる講義です。 そこで 足し算、引き算のみを用いて割り算、剰余、指数、対数を計算する手続きを作れという問題が出されました。 割り算、剰余は procedure z = x div y: begin u1 := x; u2 := y; z := 0; while u1 >= u2 do begin u1 := u1 - u2; z := z + 1; end end procedure z = x mod y: begin u1 := x; u2 := y; z := 0; while u1 >= u2 do begin u1 := u1 - u2; z := u1; end end という手続きでできそうだとわかりました。 (C言語で似たような関数をつくり確認しました。) しかし、指数と対数を求める手続き procedure z := x ** y: と procedure z := log2 x: がどうすればよいか分かりません。 この2つを教えていただけないでしょうか? プログラムの流れが分かればいいので足し算引き算のみ使用しているならC言語でもいいです! よろしくお願いします。

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

  • ベストアンサー
  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.3

C言語で作成しました。動作確認済みです。 ---------------------------------------- #include <stdio.h> #include <stdlib.h> // x,yは自然数である。従ってx>0,y>の整数とする。 //[while]に敬意を表し、for文でなく、while文で //プログラムを作成する // x*yの結果を返す関数 // これは、powerから呼ばれる補助関数 int multiply(int x,int y) { int i = 1; int ans = x; //xをy回たせば、掛け算になる while(i < y){ ans = ans + x; i++; } return ans; } // x**yの結果を返す関数 int power(int x,int y) { //x*xをy回繰り返す。 int ans = x; int i = 1; //x*xをy回繰り返すと、x**yになる while(i < y){ ans = multiply(ans,x); i++; } return ans; } // x/yを返す関数 // これは、log2から呼ばれる補助関数 int divide(int x,int y) { int ans = 0; //xからy回引き算すると割り算になる while(x >= y){ x = x - y; ans++; } return ans; } // log2 x を返す関数 (2を底とするxの対数) int log2(int x) { int ans = 0; //xを2で1になるまで割る。(1より大きい間実行) //その回数が求める解 while (x > 1){ ans++; // y/2を求める x = divide(x,2); } return ans; } int main(int argc , char **argv) { int ans; ans = power(2,4); printf("2**4=%d\n",ans); ans = log2(16); printf("log2 16=%d\n",ans); }

その他の回答 (3)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

#2 の補足のところに対してですが, 「計算の可能性」という表現からすると, おそらく while プログラムは「計算のモデル」として使っているんじゃないかなぁという気がします. そういう意味では, まさに「数学で使うことを目的にしている」といっていいかと思います. 計算モデルとしては Turing機械がもっとも一般的に使われていると思いますが, 正直いって「実際に使うととっても面倒」なので, より記述しやすい (かつ等価な) モデルを使うこともあります. こちらだと普通は RAM (Random Access Machine) のような気がしますが, while プログラムでもほぼ同じです.

  • tatsu99
  • ベストアンサー率52% (391/751)
回答No.2

x,yは正の整数という前提でよいのですか。 負の値も含みますか。 実数も含みますか。 その前提がわかると、良い回答が得られるかと思います。

avasted
質問者

補足

教科書によると、whileプログラムは自然数のみを扱うようです。 whileプログラムというプログラム自体自分も聞いたことが無く、今受けている講義で初めて知りました。 おそらく実用的なC等とは違い、数学で使うことを目的に作られたもののようですね。

回答No.1

うーん。自信ない。現状x,y,zが整数になっているけど, それ以外のケースってどうやったらいいんだろう・・・ とりあえず整数だけに限る。 ある関数に含まれる全ての関数が加算・減算のみで出来ているなら その関数は加算・減算のみで出来る、よね?多分・・・・A ====================================== 一気に累乗を考えると混乱するので, 累乗を掛け算で示す。 x**y = x * x * x *・・・ ってのをy回繰り返したものだよね? x * yってどうやるかって言ったら(yが整数なら) xをy回足せばいい。 C#が自分は慣れているのでC#で書くなら multiple(x,y) = x * yは以下のように書く。 namespace Q3694102 { class Program { public static void Main(string[] args) { System.Console.WriteLine(multiple(2,3).ToString()); /* 表示するだけ */ System.Console.ReadKey(true); /* キーを押すまで待機 */ } public static int multiple(int x,int y) { int z = 0; for (int i=y;i>0;i--){ z = z + x; } return z; } } となる。 ========================================================== pow関数は namespace Q3694102 { class Program { public static void Main(string[] args) { System.Console.WriteLine(pow(2,3).ToString()); /* 表示するだけ */ System.Console.ReadKey(true); /* キーを押すまで待機 */ } public static int pow(int x,int y){ int z = 1; for(int i = y;i>0;i--){ z = multiple(z,x); } } public static int multiple(int x,int y) { int z = 0; for (int i=y;i>0;i--){ z = z + x; } return z; } } となるだろう。 ==================== Aがあるので,後は展開するだけ。 変数のスコープが違うから同じ名前の変数が混在していたが, 一つに纏めるとなったら呼び出し元の同名変数を書き換えないように, 仮引数用の変数に書き換える namespace Q3694102 { class Program { public static void Main(string[] args) { System.Console.WriteLine(pow(2,3).ToString()); /* 表示するだけ */ System.Console.ReadKey(true); /* キーを押すまで待機 */ } public static int pow(int x,int y){ int z = 1; for(int i = y;i>0;i--){ //multiple関数の展開,ここから int m = 0; for (int j = x;j>0;j--){ m = m + z; } z = m; } return z; } } } =============================== 次,対数。 z := log2 x: 要するに, 2**z = x; となるような整数zをループ回して探せ、と。 namespace Q3694102 { class Program { public static void Main(string[] args) { System.Console.WriteLine(log(2,3).ToString()); /* 表示するだけ */ System.Console.ReadKey(true); /* キーを押すまで待機 */ } public static int pow(int x,int y){ int z = 1; for(int i = y;i>0;i--){ //multiple関数の展開,ここから int m = 0; for (int j = x;j>0;j--){ m = m + z; } z = m; } return z; } public static int log(int x,int y){ int z = 0; int i = 1; while(true){ /* 本当はオーバーフローとか気にしないといけない。*/ if (pow(x,i) > y){ break; } z = z + 1; i = i + 1; } return i - 1; } } } 後はこれを展開するだけ。面倒くさいけど。 ================================== x,yが整数でなかったときの考察。 桁が許せば,になるけれど, xとかyとかzがコンピュータであらわせる小数ってとき x = a[0] * 2**(0) + a[1] * 2**(-1) + a[2] * 2**(-2) とかになる。 上の例ならxに2**2掛ければ整数になるんじゃね? zが整数でないとき。 うーん。 実数同士の掛け算・割り算が使えそうなら 2分法みたいので狭める手が使えるとは思うんだけど。 ================================== x,yが整数でなかったときの考察。 桁が許せば,になるけれど, xとかyとかzがコンピュータであらわせる小数ってとき x = a[0] * 2**(0) + a[1] * 2**(-1) + a[2] * 2**(-2) とかになる。 上の例ならxに2**2掛ければ整数になるんじゃね? zが整数でないとき。 うーん。 実数同士の掛け算・割り算が使えそうなら 2分法みたいので狭める手が使えるとは思うんだけど。 =========================== ●x,yが負の時 ●そもそもそんな解が存在しないとき。 log2(-1)とか 面倒くさいので考えてません。 ============================

関連するQ&A

  • ある二つの数の足し算を間違え、引き算にしたら、5.7になった

    ある二つの数の足し算を間違え、引き算にしたら、5.7になった 正しい答えとのその差13 ある数とは? これはどうといたらいいですか x+y=Z x-y=5.7 そのつぎはどうやったらよいでしょう?

  • 演算を集合としてみると

    演算を集合の要素として見ると、足し算-引き算、掛け算ー割り算、微分-積分、指数ー対数を御互いに逆元と呼べますか。このように考えた場合、逆元が見つからないような演算はないのですか。また演算の数は無限にあるのでしょうか?

  • 2次式の平方根の足し算

    y^2=21*x^2-30*x+25 z^2=21*x^2-15*x+25/4 この時のy+zの最小値を求める。 平方根同志の足し算になってしまい、解けないのですが、 やり方お教え下さい よろしくお願いします。

  • 演算子オーバーロード?

    下記記載の Vector& operator+=(Vector u) メソッドの意味が理解できません。 inline Vector& Vector::operator+=(Vector u)とはどういう意味なのでしょうか? 質問がへたくそで申し訳ないのですが、どのたかご回答お願いします。 class Vector{ public: float x; float y; float z; }; inline Vector& Vector::operator+=(Vector u) { x += u.x; y += u.y; z += u.z; return *this; }

  • Delphiで論理積の足し算?

    Delphiでa=17を 0x0Fで論理積したものにb=2を足したいのですが [DCC エラー] SDIMAIN.pas(92): E2015 この型には指定した演算子は使えません となります。Integer型の論理積や足し算をしてInteger型に代入する方法はありますか? procedure TSDIAppForm.Button1Click(Sender: TObject); var a, b, c : Integer; begin a := 17; b := 2; c := (a and #$0F) + b; //c := a + b; ShowMessage(Format('c=%6d', [c])); end;

  • これはどうやって計算すればいいですか??

    これはどうやって計算すればいいですか?? プログラミングしているときにわからない式が出てきて困っています. 昔,授業で習った気もするのですが,どうしても思い出せません. 計算方法が分からない式は画像でアップしました. ベクトルu1:(x1,y1,z1) ← 既知 ベクトルu2:(x2,y2,z2) ← 既知 ベクトルu3:(x3,y3,z3) ← 求めたいベクトル としたときに, u1×u2は外積で,(y1 * z2 - y2 * z1, z1 *x2 - z2 * x1, x1 * y2 - x2 * y1)すればベクトルが出ててくるのはわかったのですが, |u1×u2|の計算方法がわかりません.(これはベクトルの大きさですか?それとも,別の意味ですか?) また,u1×u2に対して,|u1×u2|でわって,|u1|をかける方法がわかりません. 普通に成分に対する掛け算と割り算でいいのでしょうか?? できるだけ,早く回答していただけると非常に助かります. また,この式の意味がわかる方いましたら,それも教えていただけると助かります. 2つのベクトルが直交しているときに,その2つのベクトルに直交しているベクトルを求めるってことであっているのでしょうか?

  • クイックソート後の出力(pascal)

    20個の整数データをクイックソートして出力せよ、という課題が出ました。クイックソートまでは出来た(コンパイルできたのでおそらく)のですが、その順に出力する方法がわかりません。どなたかお教えください。 program sort(input,output); const n = 20; type index = 1..n; var A : array[1..n] of integer; i,x,a : integer; p,j,k : index; function PIVOT(i,j : index):integer; var k:index; begin k:=i+1; while (A[i]=A[k]) and (k<=j) do k:=k+1; if k>j then PIVOT:=0 else if A[i]>=A[k] then PIVOT:=i else PIVOT:=k end; procedure SWAP(var x,y:integer); var temp:integer; begin temp:=x; x:=y; y:=temp end; procedure PARTITION(i,j:index; a:integer; var k:index); var l,r:index; begin l:=i; r:=j; while A[l]<a do l:=l+1; while A[r]>=a do r:=r-1; while l<=r do begin SWAP(A[l],A[r]); l:=l+1; r:=r-1; while A[l]<a do l:=l+1; while A[r]>=a do r:=r-1; end; k:=l end; procedure QUICKSORT(i,j:index); var a:integer; p:index; k:index; begin p:=PIVOT(i,j); if p<>0 then begin a:=A[p]; PARTITION(i,j,a,k); QUICKSORT(i,k-1); QUICKSORT(k,j) end end; begin i:=0; i:=1+1; for i:= 1 to n do begin A[i]:=0; end; i:=0; i:=i+1; for i:= 1 to n do begin readln(x); A[i]:=x end; a:=PIVOT(p,j); PARTITION(p,j,A[a],k); QUICKSORT(p,j) end. QUICKSORT(p,j)とend. の間に出力方法を書き込みたいのです。

  • c言語のプログラムです

    2つの生の整数の割り算a÷bはaからbを繰り返し引いていき、引くことが出来なくなるまでの回数を商、その時の残りを剰余をすることで、引き算だけを用いて実現することができる。このことを考慮して、while文と引き算だけを用いて割り算を実現しなさい。という問題なんですけどどのようにプログラムを作っていいやらわかりません 一様ヒントはあります ・変数としては、入力する二つの整数に対応する変数m,n、商に対応する変数q、剰余に対応する変数rを使うとよいでしょう。すべて整数ですのでintで宣言する。 皆さんのご協力お願いします

  • 対数から指数方程式への変換

    ある実測値から ln( y )= -1E-14x^6 + 9E-11x^5 - 8E-08x^4 + 3E-05x^3 - 0.0052x^2 + 0.3843x + 1.5263 R2 = 0.9939 という方程式が導き出されました。 これを y=… という式に変換したいのですが、どうなりますでしょうか? y=exp( -1E-14x^6 + 9E-11x^5 - 8E-08x^4 + 3E-05x^3 - 0.0052x^2 + 0.3843x + 1.5263) までは教えて貰いました。 足し算引き算が、かけ算割り算になるような記憶があります。 そしてあるていど係数がまとまる気がしております。 高校生以来何十年も経ち、記憶が曖昧ですので、どうぞよろしくお願いいたします。

  • 【pic】ビットを取り出して、足し算、出力

    問 PORTB に信号を入力する。この信号のうち、上位4ビットと下位4ビットを取り出し、それぞれを足し算して、PORTAに出力するプログラムを作成せよ。以下を参考にせよ。 参考 #include <pic.h> void main(void) { int x, y, z; TRISA = 0x00; TRISB = 0xFF; for(;;) { x = (0b11000000 & PORTB) >> 6; y = (0b00111000 & PORTB) >> 3; PORTA = x; } } ということで、実際に作っては見たのですが、あっているかどうかも不明です。特に苦手な分野ですので詳しい解説の方よろしくお願い致します。 自身で書いてみたプログラム↓ #include <pic.h> void main(void) { int x, y, z; TRISA = 0x00; TRISB = 0xFF; for(;;) { x = (0b11000000 & PORTB) >> 4; y = (0b00111000 & PORTB) << 0; z = x + y; PORTA = z; } }

専門家に質問してみよう