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

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

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

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

Q&A

解決済

4回答

3364閲覧

浮動小数点の誤差を確認する方法と気を付けないといけないことが知りたい。

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

6クリップ

投稿2020/07/22 17:02

編集2020/07/23 01:22

提示コードのコメント欄の実行結果にもある通り浮動小数点の誤差を確認出来たのですがこれは値が割り切れない時に値を丸まるという処理の誤差です。 そのほかどんな誤差が生まれるのでしょうか?それとその修正方法が知りたいです。

参考サイト https://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html

#include "stdio.h" #include "math.h" int main() { double b = sqrt(2.0); float a = sqrt(2.0); printf(" 電卓計算: 1.41421356237\n"); printf(" double型計算: %.15f\n",b); printf(" float型計算: %.15f\n",a); /*実行結果 電卓計算: 1.41421356237 double型計算: 1.414213562373095 float型計算: 1.414213538169861 */ return 0; }

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

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

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

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

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

shisha

2020/07/22 18:48

もしかして、電卓の計算結果の方が(C言語より)精度が高いと考えていますでしょうか?
SHOMI

2020/07/22 19:03

printf(" double型計算: %.15f\n",b);
退会済みユーザー

退会済みユーザー

2020/07/23 00:37

提示コードを修正しましたが誤差に関する質問の回答できますでしょうか?
stdio

2020/07/23 01:05

タイトルで「気お付けない」ではなく「気を付けない」ですね。
stdio

2020/07/23 01:09 編集

JavaならBigDecimalという10進数で数字を扱う為のクラスが存在します。 電卓作りたいなら、Javaを使っても良いと思います。 もしくはC言語でBigDecimalを貴方が開発するかですね。
guest

回答4

0

提示コードのコメント欄の実行結果にもある通り浮動小数点の誤差を確認出来たのですがこれは値が割り切れない時に値を丸まるという処理の誤差です。 そのほかどんな誤差が生まれるのでしょうか?それとその修正方法が知りたいです。

浮動小数点数の丸め誤差は、表現可能な桁数が有限な浮動小数点数で実数を表現するという制約により生じる誤差です。例えば、円周率を3桁しか表せないとしたら、正確に表せるのは 3.14 までで誤差として π-3.14 が発生しますね。

丸め誤差、打ち切り誤差、情報落ち、桁落ちの意味と例 - 具体例で学ぶ数学

修正方法が知りたいです。

誤差を無くすことはできませんが、少なくする方法はあります。

1. 有効桁数を増やす

表現可能な有効桁数を増やせば誤差は少なくできます。
C/C++ の場合、プリミティブ型として float、double が用意されていますが、Boost Multiprecision Library のような多倍長浮動小数点演算が行えるライブラリを使うことで有効桁数を数百桁とかで計算することも可能です。

プリミティブ型である float/double と違い、計算速度がかなり遅くなるので、使いたい用途に対して、本当にその精度が必要かどうかを検討してから使ってください。

2. 丸め誤差が発生しにくいように計算式を組み替える

以下のように丸め誤差が大きくなるパターンというのがいくつかあるので、それを避けるように計算式を変形することで誤差を減らす工夫は可能です。

  • 情報落ち: 絶対値が大きくことなる値同士を演算して、絶対値が小さいほうの有効数字が落ちてしまう現象
  • 桁落ち: 値がほぼ同じものを減算して有効桁数が減ってしまう現象

例: chap03.pdf 例題 3.4.3 (2 次方程式の改良)

投稿2020/07/23 01:04

編集2020/07/23 01:44
tiitoi

総合スコア21956

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

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

0

ベストアンサー

ざっくり話します。

基本的に浮動小数点数は近似値であるため、そもそも浮動小数点数を使う時点で(例外はあるものの)誤差は当然あると考えるべきです。

あとは、計算を工夫して、なるべき浮動小数点数をださないようにして、誤差の影響を小さくできるかどうかです。

C言語にはないかもしれませんが、端数を扱うのに、固定小数点数や分数の型を使う方法があります。Ruby, Python, Crystal などの言語にはあります。

また、分数のように分母と分子をわけて計算するような形にしたり、計算の順序を入れ替えたり、10倍・100倍などして整数で計算して最後の結果を10・100で割ったりして、計算をできるだけ整数の型で計算するようにして、最後に浮動小数点数になるように計算するのが対処法だと思います。

投稿2020/07/23 01:06

編集2020/07/23 01:08
shisha

総合スコア86

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

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

退会済みユーザー

退会済みユーザー

2020/07/23 01:31

float型どうしをif文で == してはいけないというのも誤差の関係上だからなのでしょうか?また数式等で正確な値が知りたい場合どうすればいいのでしょうか?
maisumakun

2020/07/23 01:36

> float型どうしをif文で == してはいけないというのも誤差の関係上だからなのでしょうか? そうですね、たとえば0.3 - 0.2 == 0.1は数学的には成立しますが、doubleでは成立しません。 > 数式等で正確な値が知りたい場合どうすればいいのでしょうか? 場面に応じて手法を考える必要があります。
shisha

2020/07/23 01:58

> 数式等で正確な値が知りたい場合どうすればいいのでしょうか? もし√2や円周率の100桁目までを正確にだしたいという話であれば、私にはわからないので別に質問たてるか、なんか専門の本を読むべきだと思います。 float の結果どうしで==比較するのを避けられないのであれば、ある程度の誤差を許容して比較することが多いのではないでしょうか。「差の絶対値が0.0000001未満だったら一致してると考える」みたいな感じです。状況によっては通用しないでしょうが。 あとは、繰り返しになりますが、出来る限り計算の最初・途中・最後で浮動小数点数の型を避けることがより正確な値を求められます。浮動小数点数が避けられなさそうな具体的なケースに陥ったときに、また個別に質問たてた方が良いと思います。
退会済みユーザー

退会済みユーザー

2020/07/23 02:07

質問ですがfloat型では成立しませんでいいのでしょうか?同じくdoubleも成立しないということでいいのでしょうか?またfloatでもdoubleでも整数どうしたの計算はどうなっているのでしょうか?例 2.0 - 1.0等の計算。同じく表示させてみましたが普通に結果が出ています。
退会済みユーザー

退会済みユーザー

2020/07/23 02:10

質問2ですが。ゲーム開発等で数式を使う場合は必ずといっていいほどありますが。その場合はif文を使ってある程度小さい値になったらその数字に値を調整するという処理のコードがある場合はありますがこれはいいのでしょうか?そもそも小数点2桁で十分正確という話もありますが。
maisumakun

2020/07/23 02:21

> 質問ですがfloat型では成立しませんでいいのでしょうか? 単にJavaScriptで確認したからdoubleになっているだけで、もちろんfloatでも同様の可能性はあります。 > またfloatでもdoubleでも整数どうしたの計算はどうなっているのでしょうか? その値が「本当に」整数であれば、(桁あふれや、割り算で無限小数になるパターンを除いて)正確に計算できます。他の計算結果を持ってくる場合、「一見1.0に見えるけど、実は1.00000000000001のような微妙に違う値だった」こともありうるので要注意です。 > その場合はif文を使ってある程度小さい値になったらその数字に値を調整するという処理のコードがある場合はありますがこれはいいのでしょうか? 考え方が逆です。「それでいい」と考えたからそのようなコードを書いているのです。
shisha

2020/07/23 02:38 編集

double でも float でも同じ話です。double の方が持つデータのサイズが大きいので精度がよく誤差が小さく済みます。 > 2.0 - 1.0等の計算。同じく表示させてみましたが普通に結果が出ています。 説明が難しいですが、3.0, 2.0, 1.0 は誤差なく表せますが、0.3, 0.2, 0.1 は浮動小数点数で表せないので内部で誤差がどうしても生じています。0.1で誤差はでるけど、0.5, 0.25では誤差がでないです。浮動小数点数の原理を勉強して理解すれば、しっくり来ると思います。
guest

0

誤差が手計算と一致するか?
たまに
誤差の値に誤差があるライブラリがある

投稿2020/07/28 00:54

kokorohamoe

総合スコア190

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

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

kokorohamoe

2020/07/30 00:48

y_waiwaiさん コメントありがとうございます。今時間がないのであとでゆっくりよみます。時間切れにならないように気をつけます。
guest

0

それで確認できてるのは、あくまで2進数を10進数に変換するために出ている誤差です
同様に、10進数を2進数に変換する場合にも誤差が出ます。

浮動小数点数には(10進小数と同様に)誤差は存在しません

投稿2020/07/22 22:02

y_waiwai

総合スコア88042

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

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

Zuishin

2020/07/23 01:26 編集

進数変換の誤差もありますが、sqrt は平方根を取得する関数で、2 の平方根は無理数です。つまり進数変換以前に結果は丸められています。
y_waiwai

2020/07/23 01:28

まあたしかに、10進演算で平方根出せば誤差は生じない(ように見える)んでしょうけど、 それでいいのならまあ、そんでいいんでしょうけど。
退会済みユーザー

退会済みユーザー

2020/07/30 01:42 編集

低評価入ってますが、私は、おかしな回答ではないと思います。 (回答ですべてでは無いのは確かだけど、それは他の回答もそうかと) 誤差の発生箇所は 3 箇所あって、 ・10 進数 → 2 進数の変換箇所 ・計算の有効桁数が根拠の誤差 ・2 進数 → 10 進数の変換箇所 IEEE 的には上記で完了ですが、表示の際に追加で処理が入ることもあったはず。 毎度思うけど、厄介ですよねw
Zuishin

2020/07/23 02:04

> 浮動小数点数には(10進小数と同様に)誤差は存在しません というところに低評価しました。 無理数を丸めている以上、どちらにも誤差が存在するので。double と float で結果が異なるのも丸め誤差がもともとの原因のはずです。
退会済みユーザー

退会済みユーザー

2020/07/23 02:22

そこの表現を私は ・有効桁数内の表現において「浮動小数点数には(10進小数と同様に)誤差は存在しません」 と勝手に補完して読みました。 が、Zuishin さんの指摘のようにも読めますね。
kokorohamoe

2020/07/30 00:49

今時間がないのであとでゆっくりよみます。時間切れにならないようにがんばってよみますっ!
Zuishin

2020/07/30 00:53

> 今時間がないのであとでゆっくりよみます。時間切れにならないようにがんばってよみますっ! > y_waiwaiさん コメントありがとうございます。今時間がないのであとでゆっくりよみます。時間切れにならないように気をつけます。 kokorohamoe = syoshinsya_ ということですか。
Zuishin

2020/07/30 01:03

そして自分で自分の回答に高評価入れてる疑惑。
dodox86

2020/07/30 02:01

kokorohamoeさんの自回答への1つ目のコメント「y_waiwaiさん コメントありがとうございます。...」は投稿日時が[2020/07/30 09:48]で、こちらの回答への2つ目のコメントの投稿日時は[2020/07/30 09:49]なので、1つ目は誤爆かもしれませんね。質問内容自体に私も興味がありましたので注視してましたが、翻弄されました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問