質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

3218閲覧

IEEE規格754による実数表現について

nayuta314

総合スコア12

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

1グッド

0クリップ

投稿2017/05/01 05:43

編集2017/05/08 05:35

###質問内容
長さが32の0と1の列を入力して、このビット列の表す実数値を出力するC言語のプログラムで実数表現の仕方はIEEE規格754に従うものと仮定するCプログラムを作成したいのですが、
コンパイルして動作確認したところ正しい値が出てこないです。
どこが間違えているのかわからないです。

IEEE規格754による実数表現を行います。
長さが32の1と0の列を入力してください。:01000001011100000000000000000000

====入力ビット列は次のように解釈できます。
整数として00の値を持ち、
小数点以下0.000000の値を持ちます。
###該当のソースコード

C

1#include<stdio.h> 2#include<stdlib.h> 3int main(void){ 4 int bit[32],i,c; 5 double syosuu; 6 unsigned char unsigned_val; 7 signed char signed_val; 8 9 printf("IEEE規格754による実数表現を行います。\n" 10 "長さが32の1と0の列を入力してください。:"); 11 for(i=31;i>=0; ){ 12 switch(c=getchar()){ 13 case '0': case '1': 14 bit[i--] = c-'0'; 15 break; 16 case ' ': case '\n': case '\t': 17 break; 18 default: 19 printf("無効な文字です.\n"); 20 exit(EXIT_FAILURE); 21 } 22 } 23 24 unsigned_val = bit[31]; 25 signed_val = -bit[31]; 26 for(i=9;i>=0;i--){ 27 unsigned_val = unsigned_val*2+bit[i]; 28 signed_val = signed_val*2+bit[i]; 29 } 30 syosuu=bit[31]; 31 for(i=10;i>=31;i++){ 32 syosuu=(syosuu/2)+bit[i]; 33 } 34 printf("\n====入力ビット列は次のように解釈できます。\n" 35 "整数として%d%dの値を持ち、 \n" 36 "小数点以下%fの値を持ちます。\n", 37 signed_val,unsigned_val,syosuu); 38 return 0; 39}

###発生している問題・エラーメッセージ

IEEE規格754による実数表現を行います。
長さが32の1と0の列を入力してください。:01000001011100000000000000000000

====入力ビット列は次のように解釈できます。
整数として00の値を持ち、
小数点以下0.000000の値を持ちます。

※整数15小数点以下0.000000と出力される予定です

###追記
皆さんの意見を参考にソースコードを組み替えてみました。
ご指導のほどよろしくお願いします。

c

1 2#include<stdio.h> 3#include<stdlib.h> 4int main(void){ 5 int bit[32],i,c; 6 7 printf("IEEE規格754による実数表現を行います。\n" 8 "長さが32の1と0の列を入力してください。:"); 9 for(i=31;i>=0; ){ 10 switch(c=getchar()){ 11 case '0': case '1': 12 bit[i--] = c-'0'; 13 break; 14 case ' ': case '\n': case '\t': 15 break; 16 default: 17 printf("無効な文字です.\n"); 18 exit(EXIT_FAILURE); 19 } 20 signed char E; 21 int M; 22 int x,i; 23 char NaN,Inf; 24 E = -bit[31]; 25 for(i=9;i>=0;i--){ 26 E = E*2+bit[i]; 27 } 28 M=bit[32]; 29 for(i=10;i>=31;i++){ 30 M=M/2+bit[i]; 31 } 32 if(E==128&&M==0){ 33 printf("Inf"); 34 }else if(-127<E && E<128){ 35 x=(-1)^bit[0]*(1+M)*(2^E); 36 printf("%f",x); 37 }else if(M!=0&&E==128){ 38 printf("NaN"); 39 }else{ 40 x=(-1)^bit[0]*M*2^(E+1); 41 printf("x"); 42 } 43 } 44}
ikuwow👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

int型が32bit、float型がIEEE754のfloatであるようなC言語処理系を使う前提で、とりあえず動くであろうコード例は割合簡単(というより身も蓋もないコード)なのですが・・・

C

1int bits = 0; 2for (int i = 0; i < 32; i++) { 3 bits = (bits << 1) | bit[i]; 4} 5// この時点で32bitのビットパターンが左の桁をMSBに、右の桁がLSBとなるようにbitsに格納されている 6float fval = *(float&)&bits; 7printf("%f\n", fval);

自分が問題として出題する立場なら、上記のようなコードではなく、指数部、仮数部の範囲をしかるべく意識してそれをfloatへ変換するようなコードを求めるかも知れません。そのような回答を得るにはまずIEEE754の形式を理解する必要がありますが、この場では少々回答が長くなりますのでwikipediaのページなどを調べて形式について学んでみてください。


なお、変数unsigned_val、signed_valはchar型の幅(8bit)しかないので、32ビット分を詰め込もうとしても詰め込めません。

投稿2017/05/01 06:31

KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

外部サイトへ丸投げで申し訳ないのですが、「浮動小数点、その中身とは」 がとても参考になりそうに思いました。(waybackmachineがあってよかった)

学習が目的ならこの記事にようにパディングを含まないようにしたunionを使うと便利です。

投稿2017/05/01 08:05

sharow

総合スコア1149

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KSwordOfHaste

2017/05/01 08:20

このサイトはCのコードも色々な値の具体例ものってて分かりやすいですね!
sharow

2017/05/01 09:33

ですよね。コンパクトなのに、知識だけでもなく実装だけでもなくで、とても良いと思ったので紹介したくなりました。(サイトごと無くなってたので探すのに時間かかった…)
guest

0

ベストアンサー

IEEE単精度ですから、まず用語としては
符号(bit31)
指数部(bit30~bit23)
仮数部(bit22~bit0)
となります。
それぞれを分解したうえで、指数部については-127(本来の値に対して127の下駄をはかせているため)し、
仮数部には 1 を足さねばなりません(常に1.????? になるように正規化することで精度を1ビット多くしている)

それを踏まえますと、いろいろコードと結果の解釈が誤っていることがわかります。

計算する部分だけ書き換えるとこうなります。

C++

1 double kasuu, keta; 2 int sisuu; 3 int sign; 4 5 sign = -bit[31]; 6 sisuu = 0; 7 for (i = 30; i >= 23; i--) { 8 sisuu = sisuu * 2 + bit[i]; 9 } 10 sisuu -= 127; 11 keta = 1; 12 kasuu = 1; 13 for (i = 22; i >= 0; i--) { 14 keta /= 2; 15 kasuu += keta * bit[i]; 16 } 17

これで符号=0(正)、指数部=3(130 = 3 + 127)、仮数部 1.875 を得られますね。
(1.875 * (2^3) = 1.875 * 8 = 15)

投稿2017/05/01 06:47

tacsheaven

総合スコア13703

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問