Visual Studio 2017で試してみたら同じ結果だった
30年前の名著「数値計算の常識」を読んでたらBASICで0.01を10000回足したら100.003になるとか書いてあった。まあ昔のPCなんてそんなものかなと思いながら、Visual Studio 2017で試してみたら同じ結果だったw
— mはげ (@Tw_Mhage) Nov 17, 2018
「数値計算の常識」の最初の数ページを読むだけで、0.01を10000回足した結果の誤差の理由だけでなく、大まかな誤差の見積り方も分かった。説明は分かりやすい。薄い本だけど内容は濃い。
— mはげ (@Tw_Mhage) Nov 18, 2018
ちなみに0.01を1億回足すとこうなりますw
— mはげ (@Tw_Mhage) Nov 18, 2018
正解 1,000,000
結果 262,144
これは以下の二つが原因。実は2つ目の方が重要みたい。
— mはげ (@Tw_Mhage) Nov 18, 2018
1. 10進数を2進数に変換した際の丸め誤差
2. 大きい数と小さい数の足し算時の桁落ち
0.1を32bit浮動小数点で表しても相対誤差は6/100000000程度にしかならない。1万回足して誤差が3/100000まで増え、1億回足して74/100まで増えるのは桁落ちが原因。それは2進数かどうかとは関係ない。
— mはげ (@Tw_Mhage) Nov 18, 2018
例えば10進数で有効数字5桁で計算していると10000に1.4を足しても1しか増えないのと同じ。
桁落ちを緩和する方法を考えてみた。大きい総和に小さい数を足すからダメなので、10個ずつ足したものをまた10個ずつ足すということを繰り返して1億個の総和を求めた。誤差は74/100から1/10000000に下がった。
— mはげ (@Tw_Mhage) Nov 18, 2018
スポンサーリンク
スポンサーリンク
「数値計算の常識」を読み進めて行くとこのやり方に似た方法が紹介されてた。ただし10個ずつではなく2個ずつ足してる。2分木法というらしい。探索の手法では聞いたことあるけど、数値計算でもそう呼ぶのか。
— mはげ (@Tw_Mhage) Nov 18, 2018
@ysdkz 誤差の原因は2つです。実は2つ目の方が支配的です。 また2つめは多め少な目どちらも起こりえます。
— mはげ (@Tw_Mhage) Nov 19, 2018
1. 10進数を2進数の32bit浮動小数点に変換した際の丸め誤差(表現誤差)
2. 大きい数(今までの合計)と小さい数(これから足す数)の足し算時の桁落ち誤差
「数値計算の常識」で面白い例があったのでやってみた。
— mはげ (@Tw_Mhage) Nov 19, 2018
y = xを0から10の間で数値積分。厳密解は50。分割数Nを増やせば誤差が減るかと思いきや、100万分割の時点で逆転。1億回だと完全に狂ってくる。これも桁落ち誤差が原因。面白い。
0.01を10,000回足す計算誤差、技術者なら知ってて当然というコメント多いなw
— mはげ (@Tw_Mhage) Nov 19, 2018
自分は知りませんでした。今回原因を学んで色々検証したり、対策案を自分なりに考えて試したりしました。それでいいんじゃあないかな。
持ってた、名著
— p_nix (@p_nix) Nov 17, 2018
amazon.co.jp/dp/4320013433 twitter.com/Tw_Mhage/statu…
double だともうちょっとマシなんでしょうね。
— Thoton Akimoto ソトン秋元 (@Thoton) Nov 17, 2018
twitter.com/Tw_Mhage/statu…
Rで試してみたら,printでは一見100だけどdputだと違ってて,お主騙したな!! ってなる.
— atusy (@Atsushi776) Nov 17, 2018
> for(i in numeric(1e4)) x <- x + 0.01
> x
[1] 100
> dput(x)
100.000000000014 twitter.com/Tw_Mhage/statu…
スポンサーリンク
スポンサーリンク
逆に昔のMSX BASICならBCDだから、この答え100きっかりになるんじゃないかなあ?
— Mune-san (@MuneOiz) Nov 18, 2018
あとで試してみよう。 twitter.com/Tw_Mhage/statu…
このケースだとDecimalを使わないと期待通りにはならないですよねー。とはいえ、なんでもかんでもDecimalを使えば良いかというとそうでもないところが難しい。 twitter.com/Tw_Mhage/statu…
— アニメ「こうしす!」公式 (@kosys_pr) Nov 18, 2018
これは2進数で少数を表すときの問題なので、言語とか性能とかの問題ではないんですよ。2進数の0.1は10進数の0.5で基本これを半分にしていった数値しか2進数では表せないという本質的な問題なので、計算機で数値計算をする人間には確かに常識。
— Tuba56@法律の素人 (@Tuba56) Nov 18, 2018
twitter.com/Tw_Mhage/statu…
(っ´▽`)っ decimal型だとちゃんと100になるはず。
— そっきん (@sokkin_sokkin) Nov 18, 2018
0.01は2進数だと循環小数になるから、そんなもん足したら丸目誤差が効いてくるだろうねえ。 twitter.com/Tw_Mhage/statu…
計算結果は、計算速度などの計算性能ではなく、浮動小数点の計算仕様で決まるものだからね。これからも簡単には変わらないでしょうね。 twitter.com/Tw_Mhage/statu…
— Limg (@LimgTW) Nov 18, 2018
年月が経てば変わる思考を変えるところから始めたほうがいい。 twitter.com/Tw_Mhage/statu…
— htnari (@htnari) Nov 18, 2018
浮動小数点っていう小数点数を扱う方式の問題だから、その方式を使ってる所では、時代、言語に関係なく出ちゃうね twitter.com/Tw_Mhage/statu…
— asakurah (@asakurah) Nov 18, 2018
スポンサーリンク
スポンサーリンク
Flashからswfとwavの2つを書き出し、プレミアに入れてみると音声がビミョーに長い(3分で5frくらい)。もしかしたらFlashはエンコードにBasic使っているのかも。 twitter.com/Tw_Mhage/statu…
— 青木隆志@Flashアニメーター (@jigokuhen) Nov 18, 2018
たまにこういうのあるよね
— 生焼け案件 (@namayakeanken) Nov 18, 2018
数値計算に使う時何か不具合があるんじゃないかと不安 twitter.com/Tw_Mhage/statu…
計算機の性能が上がれば演算の精度も上がるだろうという期待は一般の方々ならありそう。
— cxq05556 (@gutenpost5) Nov 18, 2018
計算機屋さんは世間一般の認識との乖離を意識しておかないとなんかいろいろ危なそうです。 twitter.com/Tw_Mhage/statu…
twitter.com/Tw_Mhage/statu…
— 斉藤+ (@saito10th) Nov 18, 2018
絶対その本に誤差の理由書いてあると思うんだけど、これが普通の感覚なのでしょうか
時代とともに変わったりしたらとっても困る・・・(^_^;) twitter.com/Tw_Mhage/statu…
— Hiroshi Matsumura (@hmatsumu) Nov 18, 2018
この誤差問題は基本的にコンピュータは数値を2進数で扱うため10進数で0.1というキリのよい値でも2進数では循環小数となり有限の桁では表記できないためです。プチコン3号でもこの問題があるため実数型(倍精度浮動小数点型)で小数を使う際には注意が必要です。ochameclub.web.fc2.com/petitcom3/lect… #petitcom twitter.com/Tw_Mhage/statu…
— おちゃめ (@ochame_nako) Nov 18, 2018
floatだからってことはない?
— shelfall (@shelfall) Nov 18, 2018
doubleだったら誤差出ないとか。 twitter.com/Tw_Mhage/statu…
精度が欲しければdecimalやらbigdecimal型を使えっていうことでは twitter.com/Tw_Mhage/statu…
— ただ/だた (pinmarch) (@pinmarch_t) Nov 18, 2018
スポンサーリンク
スポンサーリンク
この記事に問題があると考えた場合、こちらから作者様にご連絡をお願いします。