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

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

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

MATLABはMathWorksで開発された数値計算や数値の視覚化のための高水準の対話型プログラミング環境です。

Q&A

解決済

3回答

3681閲覧

MATLAB:浮動小数演算時、計算結果に誤差が生じる場合と生じない場合がある理由について

Natthy

総合スコア10

MATLAB

MATLABはMathWorksで開発された数値計算や数値の視覚化のための高水準の対話型プログラミング環境です。

0グッド

0クリップ

投稿2019/02/10 14:23

編集2019/02/10 14:28

最近MATLAB(2011b)を触り始めた初学者です。
浮動小数に関わる知識は、情報処理技術者試験対策で自学した程度です。

小数/小数の除算の結果を確認していた際に、
同じような計算を行っているにもかかわらず、
誤差が生じる場合と生じない場合がありました。

5.01/0.01=501.0000 ←小数点以下あり(浮動小数演算の誤差発生) 
5.02/0.01=502.0000 ←小数点以下あり(浮動小数演算の誤差発生)
5.03/0.01=503    ←小数点以下なし

6.01/0.01=601    ←小数点以下なし
6.02/0.01=602    ←小数点以下なし
6.03/0.01=603    ←小数点以下なし

7.01/0.01=701    ←小数点以下なし
7.01/0.01=702.0000 ←小数点以下あり(浮動小数演算の誤差発生)
7.03/0.01=703    ←小数点以下なし

8.01/0.01=801    ←小数点以下なし
8.02/0.01=802.0000 ←小数点以下あり(浮動小数演算の誤差発生)
8.03/0.01=803.0000 ←小数点以下あり(浮動小数演算の誤差発生)

小数を扱っている以上、浮動小数で除算を行えば演算誤差は生じると考えていましたが、
値によっては演算誤差が生じていない場合がありました。

なぜこのような結果となるのか、
ご存知の方がいらっしゃいましたら、ご教示頂けますでしょうか。

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

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

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

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

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

guest

回答3

0

小数を扱っている以上、浮動小数で除算を行えば演算誤差は生じると考えていましたが、

値によっては演算誤差が生じていない場合がありました。

特定の値の場合だけ、誤差と誤差が打ち消しあって、たまたま正しい値になっているだけです。

投稿2019/02/10 14:45

maisumakun

総合スコア145184

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

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

0

残念ながら、浮動小数点数では0.01という数値は表現できません
ということで、演算誤差が生じていないように見えているというだけのはなしなので、
その質問は前提からして間違っています

投稿2019/02/10 14:38

y_waiwai

総合スコア87774

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

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

bochan2

2019/02/10 14:47

0.01に近い2進数で割り切れるか割り切れないかでケタの表示の仕方が変わると思ったんですがy_waiwaiさんはどう思いますか?
maisumakun

2019/02/10 14:52

Rubyを使えば「0.01.to_r」のようにして、この浮動小数点数を厳密な分数で表すことが容易にできます。 それを利用してそれぞれの割り算を計算してみましたが、きれいに割り切れるものは1つとしてありませんでした。
y_waiwai

2019/02/10 14:55

まあ、そもそも2進数の0.01はあくまで近似値ですから、それで誤差のある無しを論じるのはナンセンスですわな
bochan2

2019/02/10 15:04

maisumakunさん わざわざ検証して頂きありがとうございます デバッグしてなくてあれなのですが、どうやらnum2strexactを使うと桁数が増えて全部の場合で誤差の桁が出てきそうですね。
Natthy

2019/02/11 16:55

回答頂きありがとうございます。 前提からして間違えており、厳密に割り切れるものはなく誤差無しに見えるだけとの事ですが、 全て厳密に割り切れていないのであれば、matlabのワークスペースの変数に小数点以下表示の有無の差が生じるのは何故なのでしょうか。 近似値によってはmatlabが自動で丸める、といったソフトの動きに起因するものでしょうか?
maisumakun

2019/02/11 22:16

浮動小数点数として格納できる桁数は限られます(doubleの場合、2進法で53ビット相当)ので、それ以下の桁は何も指示しなくても丸められます。
y_waiwai

2019/02/11 22:17

あなたは、浮動小数点数を10進数で表示しています これはどういうことかわかるでしょうか。あなたが見ているのは、2進数を10進に変換しているときに出る誤差を見ているに過ぎません 演算の誤差なるものは存在しません。 あなたが見ているものは、10進数を2進に変換するときに出る誤差と、2進を10進に変換するときに出る誤差を見ているだけです #で、「その表示では」小数点以下4位で丸めてるようですね
Natthy

2019/02/13 13:59

回答頂きありがとうございます。 「前提が間違えている」と最初にご指摘頂いた点が遅ればせながら理解出来たと思います。 「5.02/0.01」の演算は近似値/近似値の演算を行っているので、 10進数演算結果との差は生じても2進数演算の結果としては誤差は生じていないとの理解です。 (もし間違えておりましたら申し訳ございません)
guest

0

ベストアンサー

5.03と0.01は、仮数部の下の桁が2ビットずらすと、ほぼ同じになります。

つまり、9.9999・・・ を3.3333・・・で割ると3になるようなことです。

追記:

C

1#include <stdio.h> 2#include <bits/types.h> 3 4void foo(double x){ 5 __uint64_t *z = (__uint64_t *)&x; 6 int i; 7 8 *z <<= 12; /* 符号部と指数部を飛ばす */ 9 for(i=0; i<52; i++){ 10 printf("%1d", !!(*z & 0x8000000000000000)); 11 *z <<= 1; 12 } 13 printf("\n"); 14} 15 16int main(){ 17 foo(5.03); 18 foo(0.01); 19}

Plain

10100000111101011100001010001111010111000010100011111 20100011110101110000101000111101011100001010001111011 3で、0.01のほうを2桁ずらすと、 40100000111101011100001010001111010111000010100011111 5 0100011110101110000101000111101011100001010001111011

投稿2019/02/10 14:55

編集2019/02/10 15:21
otn

総合スコア84557

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

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

otn

2019/02/10 15:02 編集

例が良くなかったかも。 4.28571428571428・・・ を 1.42857142857142857・・・ でわると 3 になるようなことです。 にしておきます。 循環小数の繰り返し部分が同じケース。この場合は、割り算すれば割り切れます。
Natthy

2019/02/11 16:45

回答頂きありがとうございます。 拝見し、一つ質問がございます。 「循環小数が同じケースは割り切れる」とのことでしたが 5.02/0.01と6.02/0.01はどちらも循環小数が同じケースと思います。 この2件で、小数点以下の表示の有無が分かれるのは何故なのか、 ご存知でしたらご教示いただけますでしょうか。 ※num2strで確認した各hex値  0.01:0x3f847ae147ae147b  5.02:0x4014147ae147ae14  6.02:0x4018147ae147ae14
otn

2019/02/12 04:57

見直すと、私の回答は、 > 誤差が生じる場合と生じない場合がありました。 へのそのものの回答じゃなくて、 「二進数浮動小数点で正確に表現できない数値同士で演算したときに、誤差が無くなるケースがある」 ということの説明にしかなってなかったです。 実際に誤差が発生するかどうかは、有限桁で計算を打ち切るときの丸め方によって、起こったり起こらなかったりすると言う事です。 (同じ循環部を持つ)循環小数同士の演算である事が分かれば、うまく計算する事ができるわけですが、浮動小数点フォーマットは、循環小数かどうかを表現できず、有限桁二進数そのものとして計算するしかないので。
ikadzuchi

2019/02/17 09:43

詳しくは調べていませんが、502と602は2進で1桁違いますので、誤差の出方も変わるでしょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問