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

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

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

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

Q&A

2回答

12138閲覧

【C言語】float型を指定したのに、小数点以下の計算結果が想定通りにならない

ametyan

総合スコア43

C

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

0グッド

0クリップ

投稿2018/05/25 23:39

以下の競プロのサイトの問題で計算結果が想定通りにならなかったので、質問します。
AIZU ONLINE JUDGE

最初は「floatパターン」でコーディングしましたが、100000009 2という入力に対して以下のように答えと違う結果になってしまいました。その後、「doubleパターン」にコードを修正したところ全問正解となりました。

・正解の計算結果
50000004 1 50000004.50000000
・「floatパターン」での計算結果
50000004 1 50000004.000000
・「doubleパターン」での計算結果
50000004 1 50000004.500000

floatは小数点以下の計算もOKで、数値の範囲もfloat型の中に収まっているはずなのに何故「floatパターン」だと小数点以下の計算ができなくなるのでしょうか?

■floatパターン

#include <stdio.h> int main() { long a, b, d, r; float f; scanf("%ld %ld", &a, &b); d = a / b; r = a % b; f = (float)a / b; printf("%ld %ld %f\n", d, r, f); }

■doubleパターン

#include <stdio.h> int main() { long a, b, d, r; double f; scanf("%ld %ld", &a, &b); d = a / b; r = a % b; f = (double)a / b; printf("%ld %ld %lf\n", d, r, f); }

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

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

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

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

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

guest

回答2

0

計算結果がfloatの範囲に入っていません。
floatの範囲は値域だけではなく、精度もあります。この問題はそこを調べる問題です。いい問題ですね。

その分析のために、最後の部分を以下のように変えました。片方は、普通にfloatで表示、ただし小数点以下の表示桁数を3桁にして、確実に.5 が見えるはずにします。
もう%xのほうは、32 bit のパターンとしてどうなっているか調べています。

f = (float)a / b; printf("%ld,%ld,%f\n", d, r, f); printf("%.3f %x\n",f, f); f = 50000004.500 ; printf("%.3f %x\n",f, f); return 0 ; }

結果は、
50000004,1,50000004.000000
50000004.000 20000000
50000004.000 20000000
で、4.5と入力しても.5 の部分は、32bit の範囲で表現できていません。
これで解決か、気にいったら評価お願いしますね。

投稿2018/05/26 00:14

gm300

総合スコア580

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

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

ikadzuchi

2018/05/26 15:58

「.5の部分が」表現できないというのは語弊がありますね。 50000004は0bitめ・1bitめも範囲外ですので4刻みでしか表現できていません。 言い換えれば、1の位の4もすでに意味のある値を表現できているとは言えない状況です。 また、50000004のビットパターンは「4C3EBC21」です。 %xにfloat型の変数を入れてよいものでしょうか。
guest

0

浮動小数点は、内部では、0.nnnnn x 2^n の形式で表現されているので、見た目の小数点以下と言うのは、意味がありません。 floatとdoubleの違いは、表現できる数値の範囲と共に、有効桁数の違いがあります。
確か、 float : 23bit, double: 52bit です。(仕様を確認していないので、違っていたら、すみません) それぞれ、10進数で、約7桁、約15桁。
原因はこの違いと思います。 (見たところ、9桁目でちがっているようですね)

[追記]
10^n --> 2^n に訂正。桁数は、指摘がありますが、自分として未確認なので、皆様のコメントを参照ください。仮数部は、2進数なので、0.5-1.0 の範囲ですね。

投稿2018/05/26 00:07

編集2018/05/26 11:46
pepperleaf

総合スコア6383

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

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

maisumakun

2018/05/26 01:02 編集

厳密に言えば、C言語で浮動小数点数の範囲は「決まっていません」。 もっとも、CPUなどの命令の都合もあるので、ほとんどの環境ではIEEE 754だとは思います。 floatは仮数部24ビット相当、doubleは53ビット相当です(2進法で正規化すれば、最上位ビットは常に1になるので、その分は保存を省略しています)。
otn

2018/05/26 03:38

> 0.nnnnn x 10^n 0.nnnnn x 2^n ですね。
gm300

2018/05/26 09:34

IEEE じゃない環境があれば知りたいです。ただし、以下の場合以外 - バグっている。 - 昔の装置あるいは、精度を気にしない・できない16bit以下の機械 去年、microsoftが独自の形式を使ってニューラルネットの計算の効率を上げたとか、より早く、正確に計算できる方式とかの論文が出ました。そういった例がもっとあるのか、広く使われているのか.. 有効桁数は、24bit が正しい表現だと思います。最上位は常に1で、それ故に、registerの中で記述が省略されている。という..
otn

2018/05/26 11:11

IEEE754以外でいうと、現行でははIBMメインフレーム系ですね。「仮数部 × 16の指数部乗」という形式です。同じサイズのIEEE754に比べると表現できる数値範囲が広い代わりに、精度がやや落ちます。 あと、Unixが生まれた環境であるDEC PDPやVAXでは、仮数部は0.5以上1未満に正規化されます。こちらはハードウェアとしては「昔の装置」扱いかもしれませんが、C言語規格のfrexp関数の仕様に生き残ってます。
ametyan

2018/05/26 12:38

ちょっとみなさん何を言っているのか分かりませんw
ikadzuchi

2018/05/26 15:49

> 0.nnnnn x 2^n 1.nnnnn x 2^n ですね。 そして仮数部の範囲は1.0-2.0(1以上2未満)ですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問