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

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

ただいまの
回答率

88.91%

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

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 6
  • VIEW 1,727

syoshinsya_

score 245

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

参考サイト 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;
}
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • syoshinsya_

    2020/07/23 09:37

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

    キャンセル

  • stdio

    2020/07/23 10:05

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

    キャンセル

  • stdio

    2020/07/23 10:08 編集

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

    キャンセル

回答 4

+8

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

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

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

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

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

1. 有効桁数を増やす

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

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

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

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

+4

ざっくり話します。

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

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

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

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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/23 11:10

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

    キャンセル

  • 2020/07/23 11:21

    > 質問ですがfloat型では成立しませんでいいのでしょうか?

    単にJavaScriptで確認したからdoubleになっているだけで、もちろんfloatでも同様の可能性はあります。

    > またfloatでもdoubleでも整数どうしたの計算はどうなっているのでしょうか?

    その値が「本当に」整数であれば、(桁あふれや、割り算で無限小数になるパターンを除いて)正確に計算できます。他の計算結果を持ってくる場合、「一見1.0に見えるけど、実は1.00000000000001のような微妙に違う値だった」こともありうるので要注意です。

    > その場合はif文を使ってある程度小さい値になったらその数字に値を調整するという処理のコードがある場合はありますがこれはいいのでしょうか?

    考え方が逆です。「それでいい」と考えたからそのようなコードを書いているのです。

    キャンセル

  • 2020/07/23 11:37 編集

    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では誤差がでないです。浮動小数点数の原理を勉強して理解すれば、しっくり来ると思います。

    キャンセル

-4

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/30 09:48

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

    キャンセル

-7

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

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

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/07/30 09:53

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

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

    kokorohamoe = syoshinsya_ ということですか。

    キャンセル

  • 2020/07/30 10:03

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

    キャンセル

  • 2020/07/30 11:01

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

    キャンセル

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

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

関連した質問

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