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

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

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

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

Q&A

解決済

4回答

2154閲覧

float型の変数の加算について。

maecan

総合スコア18

C

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

0グッド

1クリップ

投稿2016/02/26 13:09

ソース
コマンドプロンプト

コマンドプロンプトの画像で、なぜ2.7の次が0.1加算されずに0.99999しか加算されないのでしょうか?

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

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

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

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

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

guest

回答4

0

ベストアンサー

こんにちは。

10進数で非常に大き数字や非常に0に近い数字等を表現する時、例えば「4x10の5乗」のような表現を使いますよね?
float型は、これを2進数で表現しています。例えば「100×2の101乗」みたいなイメージです。
小数点数は、1x2の-1乗みたいになります。2の-1乗は1/2なので0.5ですね。2の-2乗は0.25です。2の-3乗は0.125です。更に2の-4乗でやっと0.0625です。

そして、0.1に近くなるよう1x2の-n乗の値を足していったものがfloatで表現できる0.1です。
1x2の-4乗 + 1x2の-5乗は0.09375になります。
0.1は1/10ですね。10=2x5ですが、5と2は互いに素なので、上記の計算をいくら続けても永遠に0.1になりません。で、できるだけ0.1に近づけた結果、0.99999・・・となるのです。

投稿2016/02/26 13:30

Chironian

総合スコア23272

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

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

maecan

2016/02/26 13:34

非常にご丁寧な回答ありがとうございます!とてもスッキリなりました!
guest

0

float型は浮動小数点数型であり正確な0.1という値を持つことが出来ません。
つまり誤差があります。
そのために繰り返し計算することで表面に現れない誤差が積もり積もって表面に現れた結果となります。

投稿2016/02/26 13:14

nakit

総合スコア410

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

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

maecan

2016/02/26 13:20

丁寧な説明ありがとうございます!納得できました!
guest

0

桁落ちしているからです。

投稿2016/02/26 13:11

issei.

総合スコア326

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

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

maecan

2016/02/26 13:22

回答ありがとうございます!32bitでは0.1を表現しきれないということであっていますか?
otn

2016/02/26 13:50

> 32bitでは0.1を表現しきれないということであっていますか? 0.1は2進数では無限小数なので、いくら長くても有限ビットでは表現できません。
guest

0

もともと、コンピュータは「0.1」を正確に表現できないのです。
コンピュータは2進法で数を扱っているため、2の累乗の和で表せない「0.1」をコンピュータが扱うと、どうしても真の「0.1」とはずれが生じます。そのずれが積み重なって、このような現象が起きます。

内部的な話を少しすると、floatは小数を32ビット使って表現します。最初の1ビットで符号を、次の8ビットで2の何乗かを表す指数を、残りの23ビットで仮数を表します。今回の0.1の場合、2進数で表すと
0.000110011001100110011...と無限に続きます。しかしビット数は有限なので途中で打ち切られます。
今回の場合、1.10011001100110011001100×2^-4となります。
この1.10011...の小数点以下の23桁分が仮数に入ります(整数部分を1とした時の小数部分最大23桁が格納される)。指数には-4が記録されます(実際に格納される値は規則に従い異なる値になる)。
このように表現された値が順次足しあわされていきます。当然足しあわされて桁が上がっていきますが、最下位は0のままです。仮数部に1100が最大限埋まっていることで0.1を表現していましたが、くり返し足すことでいずれ最下位の0が多くなり、0.1とのずれが大きくなっていきます。その結果、2.8になるべきところが、2.7999…という値になったのです。

投稿2016/02/26 13:33

編集2016/02/26 13:36
swordone

総合スコア20649

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

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

maecan

2016/02/26 13:39

非常に丁寧な回答ありがとうございます!内部的な話を拝見できると、より納得しやすくなります!ありがとうございます!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問