痔になりやすい生活習慣とは?

先日、桁上がりについて質問させていただいた者です。
加算と減算はなんとか完成したのですが、乗算と除算になって混乱してしまいました。
二進数の乗算、除算はビットシフトと関係がありますが、私の作っているものの場合はどのようなソースコードにすればよいでしょうか?
(ちなみに、bの値は2のべき乗に限定しています。)

int main(void)
{
int a,b,i;
int x[8],y[8];

puts("二つの符号なし整数を入力してください。(ただしa>bとし、bは2のべき乗の値とする)");
printf("a="); scanf("%d",&a);
printf("b="); scanf("%d",&b);
 printf("\n");


/*二進数の形に変換*/
for(i=0;i<=7;i++){
x[i]=a%2;
a=a/2;
y[i]=b%2;
b=b/2;
}
puts("aとbをそれぞれ二進数で表すと");
printf("a=");
for(i=7;i>=0;i--){
printf("%d",x[i]);
}
puts("");
printf("b=");
for(i=7;i>=0;i--){
printf("%d",y[i]);
}

printf("となります。\n\n");

    return(0);
 }

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

A 回答 (7件)

★アドバイス


>加算と減算はなんとか完成したのですが、乗算と除算になって混乱してしまいました。
 ↑
 何が混乱したのでしょうか?
>二進数の乗算、除算はビットシフトと関係がありますが、
>私の作っているものの場合はどのようなソースコードにすればよいでしょうか?
 ↑
 まずはビットシフトで乗算を作ってみましょう。
 2進数の乗算は次のようになります。(2のべき乗限定)
 例えば
 a…123
 b…32(2の5乗)
 この場合は 123 を 2 進数に変換して 01111011 とします。
 その後に 01111011 を左に 5 ビットシフトすればよいだけです。
 なお、シフトさせた結果の配列サイズは x[8] の倍 16 必要になります。
 下にそのサンプルを載せておきます。

サンプル:
int x[ 8 ] = { 1, 1, 0, 1, 1, 1, 1, 0 }; ←10進数で 123 を表す
int y[ 8 ] = { 0, 0, 0, 0, 0, 1, 0, 0 }; ←10進数で 32 を表す
int z[ 16 ]; ←シフトした結果を格納
int shift; ←シフトするビット数

// シフト数を算出
for ( shift = i = 0; i < 8 ; i++ ){
 if ( y[i] == 1 ){
  shift = i;
  break;
 }
}
// 初期化
for ( i = 0 ; i < 16 ; i++ ){ ←z[16]の回数
 z[ i ] = 0;
}
// 左シフト
for ( i = 0 ; i < 8 ; i++ ){ ←x[8]の回数
 z[ i + shift ] = x[ i ];
}
// z = x * y の表示
printf( "z=" );
for ( i = 15 ; i >= 0 ; i-- ){
 printf( "%d", z[i] );
}
printf( "\n" );

説明:
・上記のサンプルをつければ b が 2 のべき乗限定で乗算らしきものが出来ます。
 前回の加算は 8 ビットでしたよね。すると乗算も除算も 8 ビットという事ですよね。
 乗算も除算も演算は倍の 16 ビット分のサイズが必要になります。ここ注意!
・あと上記のサンプルの x, y に直接 2 進値を入れていますが x[0]、y[0] が下位ビット
 になります。これは質問者さんの仕様に合わせています。

その他:
・ちゃんとした乗算(2のべき乗限定ではないタイプ)を行いたい場合は次のようになります。
 a=123
 b=12
 の場合は
 a=01111011
 b=00001100
 となるので b の下位ビットから順番にスキャンして 0 ならそのまま、1 なら a を自分の
 ビット数だけ左シフトすれば良い。この結果を倍の 16 ビット配列に加算していけばやがて
 b のすべてのビットを処理したとき a と b の乗算結果になります。
・除算は別の機会にアドバイスします。まずは乗算を作ってみて下さい。
・以上。
    • good
    • 0
この回答へのお礼

回答ありがとうございます!私はビットシフトのことが完全に把握できていなかったので混乱してしまっていたんです。
なので、アドバイス通りにまずは乗算からじっくり理解したいと思います。

お礼日時:2007/07/07 08:54

★回答者 No.6 です。

修正です。
・最後の部分でキャストすればよいとアドバイスしましたが一部、間違いました。
 間違い⇒ #define LONGMASK ((LONGINT1)(~((~0UL) << LONGBITS)))
 正しい⇒ #define LONGMASK ((LONGINT2)(~((~0UL) << LONGBITS)))
 ※LONGINT1 を LONGINT2 にして下さい。
・以上です。
    • good
    • 0

★そうでしたか。


>私は自分で学習したところ(まだ初めて2ヶ月くらいですが)までの内容でどこまでできるかという挑戦で
>作り始めたので、この形で完成させてみたいと思っています。
 ↑
 薄々は感じてはいましたけど。
 ソース上で二進数の形に変換するとき 2 で割ったあまりを x[i] にセットして a = a/2; を
 行っていますね。私ならビット演算で AND、右シフトしてセットします。
 つまり、
 /*二進数の形に変換*/
 for ( i = 0 ; i < 8 ; i++ ){ ←ここは 8 にする(8Bitなので分かりやすく)
  x[ i ] = a & 0x1; ←2 で割ったあまり 0、1 がセットされる
  y[ i ] = b & 0x1;
  a >>= 1; ←2 で割ったのと同じ効果になる
  b >>= 1;
 }
 ↑
 こんな感じです。
 でも多分、ビット演算はまだ知らないのでしょうね。
 下の『参考URL』をどうぞ。

>2のべき乗以外で掛け算できるようにはしようとは思っていません。
>上に書いたように初心者ですので、恥ずかしながら今のところは簡単にしようと思っています。
 ↑
 やっぱりプログラミングを簡単に行うために限定していたのですね。
 でもこれをきっかけに 2 のべき乗以外でも掛け算できるように考えてみてはどう。
 もし出来たらスキルアップしますよ。
>一塊を 8 個の配列にセットして扱っているのは、そういう方法しか思いつかなかったので、
>そうしただけであって、特に意図はありません。
 ↑
 これは質問者さんの仕様という事ですね。
 分かりました。
 でも、回答者 No.4 さんの言うとおりで変数はコンピュータ上で全部 2 進数で格納されています。
 なので x * y とすれば 2 進数の演算を行ったことにもなるのです。
 でも 2 進数の演算を理解するという目的では今回の質問はそれなりに意味があります。
 理由は今回の方式で四則演算が出来ればその後に『多倍長演算』の考えに繋がりますので。

●質問者さんとVTClient さんへ。
>で当確する桁数ビットマスクを得る
>と言う、解釈でよいのでしょうか?
 ↑
 そうですね。解釈は正しいです。
・add() 関数で 8 ビットの最大値 0xFF を定義すればよいのですが、LONGBITS だけを
 可変すれば自動的に作成してくれるようにしたためです。これなら 7、15、20 ビットでも
 自分で 0x7F、0x7FFF、0xFFFFF としなくても良いからです。
・あとちょっと修正しますと
 #define LONGMASK (~((~0UL) << LONGBITS))
 の行は
 #define LONGMASK ((LONGINT1)(~((~0UL) << LONGBITS)))
 とキャストした方がコンパイルで警告メッセージが出ませんね。
 参考にする際はキャストした方がいいです。
・以上。

参考URL:http://www9.plala.or.jp/sgwr-t/c/sec14.html
    • good
    • 0
この回答へのお礼

回答ありがとうございます!それと、私のわがままをご理解いただきましてありがとうございます。
参考URLのおかげでビット演算が少しずつわかってきました。
これからもっと深くじっくりと理解したいと思います。

お礼日時:2007/07/07 19:46

ANo.2 です。


>アドバイスいただいたような内容はまだ私にとっては難しすぎるんです。

確かに、Oh-Orangeさんの解説は(私としても)非常に参考になります。
ただ理解できないと残念になってしまうので便乗して
Oh-Orangeさんに、ある1行でお聞きしたいのですが…、

#define LONGMASK (~((~0UL) << LONGBITS))
とは、

符号なし(UNSIGNED LONG)のコンパイル上でのnビット
(例えば通例32ビット)で
→00000000000000000000000000000000
を1補数反転
→11111111111111111111111111111111
のLONGBITS=8ビット上位シフト
→11111111111111111111111100000000
の1補数反転
→00000000000000000000000011111111

で当確する桁数ビットマスクを得る

と言う、解釈でよいのでしょうか?
(すみません、どさくさまぎれで…)
    • good
    • 0

そもそも,あなたがやってるのは2進数の計算ではありませんが..


scanf(..., &x)...scanf(..., &y)

z=x*y;
とやれば,これがすでに2進数での計算が行われています.現代のコンピュータは全部二進演算するように作られているのですから.

整数配列の各要素に1か0だけ入れて,2進数の筆算をなぞるような形で演算するというのは,効率が悪いだけで意味がありません.

何がやりたいのでしょうか?

単に頭の体操がしたいだけでしょうか?
    • good
    • 0

★回答者 No.1 です。


>私はビットシフトのことが完全に把握できていなかったので混乱してしまっていたんです。
>なので、アドバイス通りにまずは乗算からじっくり理解したいと思います。
 ↑
 それならもう少し演算についてアドバイスします。
 まず最初に乗算する b の数はなぜ 2 のべき乗でないといけないのですか?
 お聞きしたいです。もし、プログラミングを簡単に行うために限定しているのなら
 2 のべき乗以外も掛け算できるように最終的にはするつもりなのでしょうか?
 この辺はどう考えているのですか。
・あとちょっと気になったのですが 8 ビットを1つの塊として加算、減算、乗算、除算を
 実装していますよね。この一塊を 8 個の配列にセットして扱っていますが、これには何か
 意図があるのでしょうか?
・普通なら unsigned char 型で 8 ビットを管理して演算するときは 2 倍の unsigned short 型
 などで処理します。その後、8 ビットの配列× n 個に格納するようにします。
 こういうのは俗に『多倍長演算』という考えです。
・例えば『多倍長演算』という考えでの加算は下のサンプルのようになります。

サンプル:
// 記号定数
#define LONGBITS (8) // 一度に扱うビット数
#define LONGMASK (~((~0UL) << LONGBITS)) // 一度に扱うビットマスクデータ(0xFF)

// 型の再定義
typedef unsigned char LONGINT1; // 基本のデータ型
typedef unsigned short LONGINT2; // 基本のデータの倍の型

// 8 ビットを一塊とした n 個分の配列加算
int add( LONGINT ans[], LONGINT a[], LONGINT b[], int max )
{
 LONGINT2 carry = 0;
 int i;
 
 for ( i = 0 ; i < max ; i++ ){
  if ( (carry = (carry + a[i] + b[i])) > LONGMASK ){
   ans[ i ] = (LONGINT1)(carry & LONGMASK);
   carry = 1;
  }
  else{
   carry = 0;
  }
 }
 return (carry ? 1 : 0); // オーバーフローしたら 1 を返す
}

説明:
・上記のサンプルは 8 ビットを1つの塊として max 個分の配列を加算する関数です。
 8 ビットの加算では LONGINT1 a[1], LONGINT1 b[1], LONGINT1 ans[1]; と宣言して
 add( ans, a, b, 1 ); として呼び出します。
 64 ビットの加算では LONGINT1 a[8], LONGINT1 b[8], LONGINT1 ans[8]; と宣言して
 add( ans, a, b, 8 ); として呼び出します。
 800 ビットの加算では LONGINT1 a[100], LONGINT1 b[100], LONGINT1 ans[100]; と宣言して
 add( ans, a, b, 100 ); として呼び出します。
 ※いずれも戻り値はオーバーフローすれば 1 を返す事になります。
 ※800 ビットの場合は 2 の 800 乗(0~6.668e+240)までの計算が行えます。
・上記のサンプルを参考にすれば『多倍長整数演算』として何桁でも演算可能になります。
 また、同じような考えで sub(減算)、mul(乗算)、div(除算)、shl(左シフト)、shr(右シフト)
 の関数を作成して『多倍長整数演算ライブラリ』として用意するのも良いでしょう。

最後に:
・上記のサンプルでは 8 ビットを一塊として処理していますが、実際にはもっと多い 16、32 ビット
 を一塊の単位として処理した方が計算速度が速くなります。また、i カウンタを用いずにポインタ
 を使えばさらに早く演算できるようになります。増やすときは次のようにします。
 ●16 ビットの場合
 // 記号定数
 #define LONGBITS (16) // 一度に扱うビット数
 #define LONGMASK (~((~0UL) << LONGBITS)) // 一度に扱うビットマスクデータ(0xFF)
 
 // 型の再定義
 typedef unsigned short LONGINT1; // 基本のデータ型
 typedef unsigned long LONGINT2; // 基本のデータの倍の型
 
 ●32 ビットの場合
 // 記号定数
 #define LONGBITS (32) // 一度に扱うビット数
 #define LONGMASK (~((~0ULL) << LONGBITS)) // 一度に扱うビットマスクデータ(0xFF)
 
 // 型の再定義
 typedef unsigned long    LONGINT1; // 基本のデータ型
 typedef unsigned long long LONGINT2; // 基本のデータの倍の型
 ↑
 C99 規格に対応した long long 型が使えることが前提です。
 未対応のコンパイラでは 32 ビットで使います。
 ※ビット数を 16、32 に変更しても関数 add() の定義は書き換える必要はありません。
 ※そのための記号的数、型の再定義を行っているのですから。
・以上。

この回答への補足

申し訳ありません。私はほとんど初心者なので、情けないのですが、アドバイスいただいたような内容はまだ私にとっては難しすぎるんです。
私は自分で学習したところ(まだ初めて2ヶ月くらいですが)までの内容でどこまでできるかという挑戦で作り始めたので、この形で完成させてみたいと思っています。

>2 のべき乗以外も掛け算できるように最終的にはするつもりなのでしょうか?
>この一塊を 8 個の配列にセットして扱っていますが、これには何か
 意図があるのでしょうか?

2のべき乗以外で掛け算できるようにはしようとは思っていません。
上に書いたように初心者ですので、恥ずかしながら今のところは簡単にしようと思っています。一塊を 8 個の配列にセットして扱っているのは、そういう方法しか思いつかなかったので、そうしただけであって、特に意図はありません。


せっかく回答をいただいたのに自分勝手のことを言って申し訳ないです。

補足日時:2007/07/07 13:54
    • good
    • 0

実際の処理はこんな感じかと思います。



#include <stdio.h>

int nishin(int h[],int size,int a)
{
/*二進数の形に変換*/
for(int i=0;i<size;i++){
h[i]=a%2;
a=a/2;
}
return 0;
}

int main(void)
{
int x[16],y[16],a,b,i,j,m,n,p,w,z;
unsigned int size_8=8,size_16=16;
puts("二つの符号なし整数を入力してください。(ただしa>bとし、bは2のべき乗の値とする)");
do{
printf("a=");scanf("%d",&a);
printf("b=");scanf("%d",&b);
printf("\n");
if (!(a&&b)) return 0;
for(i=0x80,j=0;i;i>>=1) j+=b&i?1:0;
}while(a<=b||(a|b)>0x100||a<0||b<0||j-1);
// 入力条件を満たせば続きます

puts("aとbをそれぞれ二進数で表すと");
printf("a=");
nishin(x,size_8,a);
for(i=size_8-1;i>=0;i--){
printf("%d",x[i]);
}
puts("");
printf("b=");
nishin(y,size_8,b);
for(i=size_8-1;i>=0;i--){
printf("%d",y[i]);
}
printf("\r\n");

for(j=0,m=a,n=b;j<8;j++,n>>=1) m=n&1?m<<j:m;
printf("a*b=");//掛け算
nishin(x,size_16,m);
for(i=size_16-1;i>=0;i--){
printf("%d",x[i]);
}
printf("\r\n");
for(j=0,p=m=a,n=b,z=0,w=0;j<8;j++,n>>=1,p>>=1)
{
m=n&1?m>>j:m;
if (!(n&1) && !w) z|=(p&1)<<j,w=n>>1&1;
}
printf("a/b=");//割り算
nishin(x,size_16,m);
for(i=size_16-1;i>=0;i--){
printf("%d",x[i]);
}
printf("\r\n");
printf("a mod b=");//余り
nishin(y,size_16,z);
for(i=size_16-1;i>=0;i--){
printf("%d",y[i]);
}
printf("\r\n");

printf("\r\nとなります。\n\n");
return(0);
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます!とても参考になりました。

お礼日時:2007/07/07 08:55

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

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

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

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

Q2進数の割り算が分かりません・・・。

2進数の割り算が分かりません・・・。
授業でいきなり出てきて大変に戸惑っています。
10010➗11(2進数)
の解き方を教えてください。
よろしくお願いします・・・!

Aベストアンサー

2進数の場合の割り算は引く事が出来るか?をフラグを立てていく感じになります。

Q2進数の除算について

タイトルどおり、2進数の除算についてわからいので質問をします。
(1)割り切る方法と(2)余りを出す回答があるようなのですが、どこのサイトを見てもいまひとつ理解ができなくて困っています。何か具体的な例を挙げていただきたいと思います。

それに加えて、前者の割り切る方法の結果から分かること(法則性)も知りたいのですが、両者について分かる方がいらっしゃれば、どうかお力添えをお願いします。

Aベストアンサー

> また追加で質問なのですが、先の100001÷110=101…11で
> (1)余りを出す
> (2)割り切る という二つの計算方法があるらしく、これは(1)の計算方法なのですが、(2)の割り切るとはいったいどのような方法なのでしょうか?

多分ですが、「小数を使って割りきれ」ということだと思います。

       101
   ―――――――
110)100001
     110
    ――――
      100
        0
      ―――
      1001
       110
      ――――
        11

↓(1/2の位に進む)

       101
   ―――――――――
110)100001.0
     110
    ――――
      100
        0
      ―――
      1001
       110
      ――――
        11 0

↓(商の1/2の位の数は1)

       101.1
   ―――――――――
110)100001.0
     110
    ――――
      100
        0
      ―――
      1001
       110
      ――――
        11 0
        11 0
        ――――
           0

商は101.1

> また、その割り切った結果から何が分かるのでしょうか?

分かりません。

10進数ではどんな有限小数も、(2^n)(5^m)で割りきれます(n, mは0以上の整数)。
逆に(2^n)(5^m)で表せない数(例えば6)で割ると、割り切れない場合があります。

対して2進数では、どんな有限小数も(2^n)で割りきれます(nは0以上の整数)。
逆に(2^n)で表せない数(例えば10)で割ると、割り切れない場合があります。

そういったわり算に関する話がありますが、
先ほどのわり算1個だけからそんな結論を得るのは不可能だと思います。

> (1)2進数の補数計算の方法に関して4つまとめる

(1)の「4つ」とは何が4つなのでしょうか?
「たし算、ひき算、かけ算、わり算の4つの計算方法についてまとめなさい」ということでしょうか?
だとしたら、それぞれの計算方法について説明すれば良いと思います。
小学校の算数の教科書には、10進数のたし算やひき算や
かけ算やわり算のやり方が書いてありますよね。
あれを2進数版に書き直すような感じでいいのではないでしょうか?

まず1桁のたし算から始めて、その後繰り上がりの概念を利用して2桁以上のたし算を説明し、
次にたし算の筆算のやり方を……といった感じでやれば良いと思います。

ここの環境だと筆算の繰り上がりや繰り下がり等が表記できないので、
申し訳ないですが、計算方法のまとめを書くのは無理です。

> (2)2進数の1の補数が,ビット毎の0・1反転で得られることを証明

1の補数の定義を知らないので、大したアドバイスはできません。
とりあえず、思いついたことを書いておきます。

1桁の2進数aをビット反転させると、(1 - a)になります。

a = 0の時、(1 - a) = 1
a = 1の時、(1 - a) = 0

次に2桁以上の2進数のビット反転を考えます。
ある2進数Xのn桁目の数をx_nと表現します(x_n = 0, 1)。
この時、Xをビット反転させた数のn桁目の数は(1 - x_n)で表せます。
これは先ほどの、「1桁の2進数aをビット反転させると(1 - a)となる」という話と同じです。

後はこの「n桁目の数がx_nの2進数」と「n桁目の数が(1 - x_n)の2進数(ビット反転させた2進数)」を比較し、
1の補数の定義と合致しているかを確認すればいいと思います。

> また追加で質問なのですが、先の100001÷110=101…11で
> (1)余りを出す
> (2)割り切る という二つの計算方法があるらしく、これは(1)の計算方法なのですが、(2)の割り切るとはいったいどのような方法なのでしょうか?

多分ですが、「小数を使って割りきれ」ということだと思います。

       101
   ―――――――
110)100001
     110
    ――――
      100
        0
      ―――
      1001
       110
     ...続きを読む

Qprintf で二進表示を行いたい。

すみません。教えていただきたいことがあります。
printf で普通のintの値をフォーマット指定子を使用して二進表示をしたかったのですが見当たりませんでした。
どうにかintの内容を二進で確認したいのですが、どのようにすれば良いですか?
宜しくお願いします。

Aベストアンサー

★2進整数を表示する関数を自作すればよい。
・作り方は簡単で、最上位ビットから順に『0』と『1』を調べていき、ビットが
 立っていれば『putchar('1');』にして、ビットが OFF なら『putchar('0');』
 にすれば良いでしょう。
・下にサンプルを載せますので使いやすいように改良して下さい。

サンプル:
unsigned int bit = (1 << (sizeof(int) * 8 - 1));
int value = 12345; ←これが表示したい int 型の整数値です。

printf( "value の 2進表記は " );

for ( ; bit != 0 ; bit >>= 1 ){
 if ( value & bit ){
  putchar('1');
 }
 else{
  putchar('0');
 }
}
printf( " です。\n" );

最後に:
・1バイトが 8 ビットの環境が前提です。→まぁ、普通は 8 ビットですが…。
・上記のサンプルを関数などにすれば使いやすくなります。→print_bin()など
・以上。おわり。

★2進整数を表示する関数を自作すればよい。
・作り方は簡単で、最上位ビットから順に『0』と『1』を調べていき、ビットが
 立っていれば『putchar('1');』にして、ビットが OFF なら『putchar('0');』
 にすれば良いでしょう。
・下にサンプルを載せますので使いやすいように改良して下さい。

サンプル:
unsigned int bit = (1 << (sizeof(int) * 8 - 1));
int value = 12345; ←これが表示したい int 型の整数値です。

printf( "value の 2進表記は " );

for ( ; bit != 0 ; bit >>= 1 ){
 if...続きを読む

Q引き放し法による除算アルゴリズムについて

突然の質問失礼いたします。
現在私は学校で引き戻し法・引き放し法といった除算のアルゴリズムについて学んでいるのですが、そのうちの引き放し法について質問したく投稿しました。

引き放し法について自分で勉強しようと思い、いろいろ調べていたのですが、商と余りを出す引き放し法は見つかっても、小数点以下にわたってまで商を求める引き放し法がまったく見つかりませんでした。
(例えば5÷2=2あまり1と結果を出すのではなく、5÷2=2.5と結果を出す引き放し法のことです。)

少数点以下にわたってまで商を求める引き放し法は商と余りを出す引き放し法で表現できるのでしょうか?
もしよろしければ教えていただけると幸いです。また、参考にすべきインターネットサイト等もあれば教えていただけると助かります。

Aベストアンサー

★30÷8と考えます。
>3÷8などと言った被除数<除数の場合は同じ方法でやってみると
>解がでない気がするのですが・・・。
 ↑
 解けます。
・3÷8 は商が 0 となりますがこの時は 3×10=30 から 8 を割ればよい。
 よって
 (1)3÷8=0
 (2)30÷8=3あまり6
 と計算します。0、3あまり6 と出ますから 0.3 となるわけです。
・あまりの 6 は計算を続けて
 (3)6÷8=0
 (4)60÷8=7あまり4
 となります。ここで 0.3 に 7 を追加して 0.37 となります。
・あまりの 4 は計算を続けて
 (5)4÷8=0
 (6)40÷8=5あまり0
 となります。ここで 0.37 に 5 を追加して 0.375 となります。
・割り切れたので 3÷8=0.375 となります。
 このように『被除数<除数』の場合は10倍して繰り返します。
 それでは宿題として3÷800はどうなるでしょうか?
 出来たら補足などに書き込んでみて下さい。
・以上。

Qプログラム設計書の書き方

僕は新人SEです。
今、上司の方からあるシステムの基本設計書・システム設計書・プログラム設計書を作り、プログラミングまでしてから単体テスト・結合テストもやるように言われています。(全て1人で)

おそらく経験のある方ならすぐにできてしまうようなシステムで、上司の方も勉強のために全てやらせているようです。

今、基本設計書・システム設計書まではなんとかできて、プログラム設計書の作成に取り掛かりたいのですが、初めての経験で実際のプログラム設計書には何をどのように書いているものなのかも全く見当もつかずにいるので全く何も書けません。

上司さんは今週忙しいようで
「来週見てあげるから自分で調べたりしてやってみて」
と言っています。
ですが、全く何もできずにいるのもイヤなので何かそれらしいものでも書いてみたいのですが…プログラム設計書とは何をどう書いてあるものなのでしょうか?

日本語が書いてあるのかプログラムが書いてあるものなのか…
そういったところからわからないので少しでも何か教えていただきたいです。
宜しくお願いします。

Aベストアンサー

こんにちは。
No.1様のご回答通りなのですが会社によって異なります。
というのを踏まえた上で・・・うちではという回答になりますが

・日付 2009/10/10
・版 初版(その後バージョンアップで改定するため、改定ナンバー必須)
・タイトル 企業情報印刷(ここでは決定済み名称)
・発注仕様書ナンバー(正式にお客さまと契約で決めた発注番号を記載)
・作成者 boo_boo_suu
・使用言語 Visual C++
・使用データベース ORACLE
・使用帳票アプリケーション Crystal Reports
・フロー図(Visioで埋め込み図)
・概要説明 
メインメニューから呼び出され企業情報の印刷条件を入力し、クリスタルレポートの帳票情報から企業情報ファイル(KIGYOU_INFO)ファイルを呼び出し印字します。
・全企業情報が一覧で印字可能である。
・特定一企業(企業コード指定)での印字も可能である。
・一企業が指定された場合は企業情報を画面表示する。

-----------------------------------
で・・・・プログラム仕様書はこのくらい。
命令書ですからコードそのものは打ちません。
これみて作ってもらわないといけないので日本語メインです。

あとはDBの仕様書をみてもらったりしてプログラムのローカルルール、画面サイズ、文字サイズ プロシージャ定義やら定数や変数、フォーム、構造体定義書などプログラム書くときの決まりごとに添ってPGさんに打ってもらっています。
一応、図とかつけてみました。(^-^;;
全体の雰囲気はこんな感じだとご理解いただければ幸いです。
ではでは~。

こんにちは。
No.1様のご回答通りなのですが会社によって異なります。
というのを踏まえた上で・・・うちではという回答になりますが

・日付 2009/10/10
・版 初版(その後バージョンアップで改定するため、改定ナンバー必須)
・タイトル 企業情報印刷(ここでは決定済み名称)
・発注仕様書ナンバー(正式にお客さまと契約で決めた発注番号を記載)
・作成者 boo_boo_suu
・使用言語 Visual C++
・使用データベース ORACLE
・使用帳票アプリケーション Crystal Reports
・フロー図(Visioで...続きを読む

Q2進数の足し算(C言語)

C言語初学者です。
タイトル通り、2進数の足し算をするプログラムを作っていますが、行き詰ってしまいました。
特に、桁上げをどうするか悩んでいます。
今の自分の考えでは、入力された数値を10で割り、その余りを足していけばできると思っていたのですが、やはり桁上げや繰り上がりに悩んでいます。
全然できてませんが以下ソースです。

#include <stdio.h>

int main(void)
{
int a, b, i;

do {
printf("8桁以下の非負の2進数を入力してください(1つ目): ");
scanf("%d" ,&a);
if (a < 0)
puts("負の数を入力しないでください。");
} while (a < 0);

do {
printf("8桁以下の非負の2進数を入力してください(2つ目): ");
scanf("%d" ,&b);
if (b < 0)
puts("負の数を入力しないでください。");
} while (b < 0);

a = a % 10;
b = b % 10;

よろしくお願いします。

C言語初学者です。
タイトル通り、2進数の足し算をするプログラムを作っていますが、行き詰ってしまいました。
特に、桁上げをどうするか悩んでいます。
今の自分の考えでは、入力された数値を10で割り、その余りを足していけばできると思っていたのですが、やはり桁上げや繰り上がりに悩んでいます。
全然できてませんが以下ソースです。

#include <stdio.h>

int main(void)
{
int a, b, i;

do {
printf("8桁以下の非負の2進数を入力してください(1つ目): ");
scanf("%d" ,&a);
if (a...続きを読む

Aベストアンサー

ちょっと質問者の意図とは違うかもしれないですが…


論理回路をそのままプログラムに直したような感じではどうでしょう。

2進数数値を入力してもらうときに、文字列配列へ入力してもらいます。
// scanf("%s", A) など
2つの値をそれぞれ A B として、各ビット(要素)について、加算器と同様の演算をします。
#参考URLを参照してください


例として4ビットでやってみると…
要素:3 2 1 0
-------------
 A:0 0 1 1
 B:1 0 0 1

0番目の要素 A[0]:1 B[0]:1 について、足し算の結果 S と繰り上げのフラグ C という配列に
S[0] = 1 + 1 = 0
C[0] = 1(桁上げあり)
と格納します。
#Sは2値のExOR、Cは2値のANDです。

次の桁では、C の値を考慮し…
S[1] = A[1]:1 + B[1]:0 + C[0]:1 = 0
C[1] = 1(桁上げあり)
#C[1] は A[1],B[1],C[0]のうち2つ以上が 1 なら 1

S[2] = A[2]:1 + B[2]:0 + C[1]:1 = 1
C[2] = 0(桁上げなし)
 :
 :
これを各桁についてすべて行うと、結果がでるはず。

(これを2進数のまま表示するなら、S 配列を出力すればいいですし、10進にするなら…変換が必要です。)


どうしても、int型の値を使い1つの変数で表したい場合は、10で割って余りを求めていくしかないですね。
でも、基本的に演算内容は論理回路と似てるはずなので、参考にしてください。


Wikipedia - 加算器

参考URL:http://ja.wikipedia.org/wiki/%E5%8A%A0%E7%AE%97%E5%99%A8

ちょっと質問者の意図とは違うかもしれないですが…


論理回路をそのままプログラムに直したような感じではどうでしょう。

2進数数値を入力してもらうときに、文字列配列へ入力してもらいます。
// scanf("%s", A) など
2つの値をそれぞれ A B として、各ビット(要素)について、加算器と同様の演算をします。
#参考URLを参照してください


例として4ビットでやってみると…
要素:3 2 1 0
-------------
 A:0 0 1 1
 B:1 0 0 1

0番目の要素 A[0]:1 B[0]:1 について、足し算の結果 S ...続きを読む

Q2進数の掛け算ができません

初めまして。2進数の掛け算で困っています。よろしくお願いします。

10進数で2*(-3)=-6ですが、これを3bitの2進数で行ないたいと思います。
すると、010*101(2の補数)=01010となります。
-6は10(2の補数)となるはずですが答えが異なります。
符号拡張というものがあるということで、次はそれで行なってみます。
010*1101(符号を拡張した2の補数)=011010となります。
答えが異なります。ますますわけがわかりません。
----------
次に10進数で(-1)*(-1)=1ですが、これを2bitの2進数で行ないたいと思います。
すると、11(2の補数)*11(2の補数)=1001となります。
1は1となるはずですが答えが異なります。
符号拡張というものがあるということで、次はそれで行なってみます。
111(符号を拡張した2の補数)*111(符号を拡張した2の補数)=110001となります。
答えが異なります。ますますわけがわかりません。
----------
話は変わるのですが、
Nビット×Mビット=N×Mビットになる
とのことです。これも理解できません。

どなたかご教授をお願いしますm(__)m

初めまして。2進数の掛け算で困っています。よろしくお願いします。

10進数で2*(-3)=-6ですが、これを3bitの2進数で行ないたいと思います。
すると、010*101(2の補数)=01010となります。
-6は10(2の補数)となるはずですが答えが異なります。
符号拡張というものがあるということで、次はそれで行なってみます。
010*1101(符号を拡張した2の補数)=011010となります。
答えが異なります。ますますわけがわかりません。
----------
次に10進数で(-1)*(-1)=1ですが、これを2bitの2進数で行ないた...続きを読む

Aベストアンサー

先ず最初に、間違いの指摘を一つ。
>Nビット×Mビット=N×Mビットになる
Nビット×MビットはN+Mビットです。
ビット数を数えることは、(2を底とした)対数演算に置き換えられます。
つまり、Nビット数であるnとMビット数であるmを考えると、
log2(n) = N, log2(m) = Mと置けます。
つまりn×mのビット数はlog2(n×m)となり、log2(n)+log2(m)となります。
更に付け加えると、符号付の場合はNビット×Mビットが(N-1)+(M-1)ビットになってしまいます。
これは符号ビットの分、有効ビット数が減るためです。

さて、最初の問題に取り掛かりましょう。
3ビット * 3ビットの演算とありますが、符号ビットがあるので有効ビットは2ビットになってしまいます。
つまり、010 * 101 = 1010となり、4((3-1)+(3-1))ビットの符号付整数となります。
これは10進数に変換すると-6です。
また、符号拡張した場合も010 * 1101 = 11010という5((3-1)+(4-1))ビットの符号付整数ですからこれも-6になります。

次の問題も同様で、11 * 11 = 01、111 * 111 = 0001と、それぞれ1になります。

先ず最初に、間違いの指摘を一つ。
>Nビット×Mビット=N×Mビットになる
Nビット×MビットはN+Mビットです。
ビット数を数えることは、(2を底とした)対数演算に置き換えられます。
つまり、Nビット数であるnとMビット数であるmを考えると、
log2(n) = N, log2(m) = Mと置けます。
つまりn×mのビット数はlog2(n×m)となり、log2(n)+log2(m)となります。
更に付け加えると、符号付の場合はNビット×Mビットが(N-1)+(M-1)ビットになってしまいます。
これは符号ビットの分、有効ビット数が減るためです。

...続きを読む

Q配列をnビットシフトする

題名の通り配列をnビットシフトする方法を教えてください。

char buf[3] = { 0x30,0xf0,0x80 }というデータで n=3 だった場合
欲しいデータはbuf[3] = { 0x06,0x1e,0x10 }です。

{ 0x30, 0xf0, 0x80 } →{ 0x06, 0x1e, 0x10 }
[ 00110000,11110000,10000000 ]→[ 00000110,00011110,00010000 ]

ご教授お願いします。

Aベストアンサー

★追記。
>これはこの処理では左にシフトしているため他のビットの値は何でもいいということでしょうか?
 ↑
 左にシフトした後で (char) 型にキャストされるからです。
 これは hi、lo 変数が char 型なので左シフトした9ビット以上が自動的にカットされるからです。
 キャストを利用すると9ビット以上をカット出来るため 0xFF で AND を取るのと同じ効果があるのです。
 同じ効果になるだけで『何でもいい』訳ではないのです。hi、lo が char 型以外だと 0xFF で
 AND を取る必要があります。
・以上。

参考URL:http://www9.plala.or.jp/sgwr-t/c/sec14.html

Q2進数の加算の繰り上がり

2進数の四則演算のプログラムを作りたいと思い、2進数を表示するところまではできたのですが、加算になると繰り上がりという壁にぶつかってしまいました。繰り上がりや桁上げなどがよく分からないので、お教えください。(下のソースコードが繰り上がりのない加算をするまでのものです)

#include <stdio.h>

int main(void)
{
int a,b,i,j,x[8],y[8],z[8];
do{
puts("二つの符号なし整数を入力してください。(ただしa>bとし、bはのべき乗の値とする)");
printf("a="); scanf("%d",&a);
printf("b="); scanf("%d",&b);

if(a < = b)
puts("入力した値がa>bになっていません。\a");
}while(a < = b);

for( i = 0; i < = 7; i + +){
x[i] = a % 2;
a = a / 2;
y[i] = b % 2;
b = b / 2;
}
puts("aとbをそれぞれ二進数で表すと");
printf("a=");
for( i = 7; i > = 0; i - -){
printf("%d",x[i]);
}
puts("");
printf("b=");
for( i = 7; i > = 0; i - -){
printf("%d",y[i]);
}

printf("となります。\n\n");

printf("<加算>\n");
printf("c=a+b=");

for( j = 7; j > = 0; j - -){
z[j]=x[j]^y[j];
printf("%d",z[j]);
}
return(0);
}

2進数の四則演算のプログラムを作りたいと思い、2進数を表示するところまではできたのですが、加算になると繰り上がりという壁にぶつかってしまいました。繰り上がりや桁上げなどがよく分からないので、お教えください。(下のソースコードが繰り上がりのない加算をするまでのものです)

#include <stdio.h>

int main(void)
{
int a,b,i,j,x[8],y[8],z[8];
do{
puts("二つの符号なし整数を入力してください。(ただしa>bとし、bはのべき乗の値とする)");
printf("a="); scanf("%d",&a);
...続きを読む

Aベストアンサー

桁上がり変数 carry を使って、

:
(前略)
:
main(void)
{
int a,b,i,j,x[8],y[8],z[8], carry=0;
:
(中略)
:
for(j=0; j<8; j++) {
z[j]=x[j]^y[j]^carry;
carry = (x[j] & y[j]) | (x[j] & carry) | (y[j] & carry);
}

if (carry != 0) printf("%d", carry);
for(j=7; j>=0; j--) {
printf("%d",z[j]);
}
:
(後略)
:

とすれば良いのではないでしょうか。

※ (a + b) を 2進数表示すれば同じ結果が得られますが、これではいけませんか。


人気Q&Aランキング