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

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

ただいまの
回答率

90.83%

  • C

    3216questions

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

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

受付中

回答 2

投稿

  • 評価
  • クリップ 0
  • VIEW 139

ametyan

score 5

以下の競プロのサイトの問題で計算結果が想定通りにならなかったので、質問します。
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);

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

+2

計算結果が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/27 00:58

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

    キャンセル

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 10:02 編集

    厳密に言えば、C言語で浮動小数点数の範囲は「決まっていません」。

    もっとも、CPUなどの命令の都合もあるので、ほとんどの環境ではIEEE 754だとは思います。

    floatは仮数部24ビット相当、doubleは53ビット相当です(2進法で正規化すれば、最上位ビットは常に1になるので、その分は保存を省略しています)。

    キャンセル

  • 2018/05/26 12:38

    > 0.nnnnn x 10^n

    0.nnnnn x 2^n ですね。

    キャンセル

  • 2018/05/26 18:34

    IEEE じゃない環境があれば知りたいです。ただし、以下の場合以外

    - バグっている。
    - 昔の装置あるいは、精度を気にしない・できない16bit以下の機械

    去年、microsoftが独自の形式を使ってニューラルネットの計算の効率を上げたとか、より早く、正確に計算できる方式とかの論文が出ました。そういった例がもっとあるのか、広く使われているのか..

    有効桁数は、24bit が正しい表現だと思います。最上位は常に1で、それ故に、registerの中で記述が省略されている。という..

    キャンセル

  • 2018/05/26 20:11

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

    キャンセル

  • 2018/05/26 21:38

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

    キャンセル

  • 2018/05/27 00:49

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

    キャンセル

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

  • ただいまの回答率 90.83%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C

    3216questions

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