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
2進数割り切れないからね。ビットレベルで仕組みを理解するのがコンピュータとの正しい接し方 twitter.com/Tw_Mhage/statu…
— タマニチェンコ (@qtamaki) Nov 18, 2018
スポンサーリンク
スポンサーリンク
0.0100003はコプロが内蔵された今なお連綿と続く単精度浮動小数点型の伝統っぽい twitter.com/Tw_Mhage/statu…
— 財団自然人ちかのん (@twittanon) Nov 18, 2018
mはげ on Twitter twitter.com/Tw_Mhage/statu…
— Kairo (@amep52) Nov 18, 2018
同じ結果じゃないと困る(ことがある)からなあ。 twitter.com/Tw_Mhage/statu…
— ななし (@nanashi74) Nov 18, 2018
ここらは 8 ビットパソコンの時代から変わらない話だなぁ twitter.com/Tw_Mhage/statu…
— Kunihiko Imai (@JR0BAK) Nov 18, 2018
数値計算屋さんから見た一言。
— さくらえび(ギリギリ在職中) (@get_apt_ebi) Nov 18, 2018
後でノルムで割ったらどうでしょう? twitter.com/Tw_Mhage/statu…
まじで!?
— 酒 (@sake_yaruo) Nov 18, 2018
しらんかったわぁ、まじ危ないね twitter.com/Tw_Mhage/statu…
これ初めて知ったとき衝撃だった twitter.com/Tw_Mhage/statu…
— Niccori250k (@Niccori250km) Nov 18, 2018
大学の授業で学んだネタだこれ。浮動小数点の扱いが変わらない限り0.5や0.125とかなら大丈夫だけど0.1はダメなので、「コンピューターの実数演算は正確ではない場合がある」実例として示すのに手っ取り早いやつ。何故ダメなのかをレポートで出させられたわ。懐かしい。 twitter.com/Tw_Mhage/statu…
— tAkihiko (@ATA911) Nov 18, 2018
カシオのFP-1000でやってみたらどうなるかだれかしらべて twitter.com/Tw_Mhage/statu…
— nzɐʞ (@hirota_kazu) Nov 18, 2018
特殊な環境で精度が低い浮動小数点使ってるとこの辺困るんだよなぁ・・・。 twitter.com/Tw_Mhage/statu…
— nano@beat saber (@nano06126728) Nov 18, 2018
スポンサーリンク
スポンサーリンク
浮動小数点演算のライブラリの仕様を変えてないんだろね。 twitter.com/Tw_Mhage/statu…
— ゆで豆 味ついてて美味しいです (@yudemame1967) Nov 18, 2018
「BASICで0.01を10000回足したら100.003になる」というやつ、
— 工作魂 (@porokin) Nov 18, 2018
twitter.com/Tw_Mhage/statu…
MachiKania type Mで確認したら、確かにそうなってた。
(どうでもいいけど、"FOR I=1 TO 10000" と書くべきだったかなぁ(^^;))
これむしろ (今の) Windows の電卓だと「きちんと 100 になる」の方が、まぁアレよね。
— 近藤 和宏 (@kondoujp) Nov 18, 2018
あと、VB なら Currency 型だと 100 になるのでは。 twitter.com/Tw_Mhage/statu…
小さなポンプの動作回数に理論値吐出量を掛け合わせた薬品使用量が棚卸時ほぼ合わない事は工業系の常識なのですが、財務系ではこれらはサラミと呼ばれいたり、中々のワルさをします。 twitter.com/Tw_Mhage/statu…
— strnh (@strnh) Nov 18, 2018
zsh -c 'n=0.0;for ((i=0;i<10000;i++)); do ((n+=0.01));done;echo $n'
— ふみやす@シェルまおう(自称でない) .JSON (@satoh_fumiyasu) Nov 19, 2018
#シェル芸 twitter.com/Tw_Mhage/statu…
ツイートを見た人の反応
— yuta (@yuta0381) Nov 19, 2018
一般人「www」
エンジニア「面白い」
リプライを見た人の反応
一般人「???」
エンジニア「面白い」 twitter.com/Tw_Mhage/statu…
その昔、みんなが浮動小数点数を使うのに二の足を踏んでいた理由はこれだったのか。 twitter.com/Tw_Mhage/statu…
— 平山 剛 (@kz0217) Nov 19, 2018
プチコン3号で試したら
— 127.0.0.1 (Godot) (@7F000001) Nov 19, 2018
100だった。
非互換…。
常識外れでした。
#petitcom twitter.com/Tw_Mhage/statu…
なんでなんだろ twitter.com/Tw_Mhage/statu…
— yn (@avocadobanan) Nov 19, 2018
今時メモリも処理性能も潤沢なのだから、素人向けの言語はあらゆる
— ねぎ式™ (@ohtsuka) Nov 19, 2018
decimal でやっても、という話かと思った。 twitter.com/Tw_Mhage/statu…
スポンサーリンク
スポンサーリンク
C#でも小数型の仕組みは変わってないよね twitter.com/Tw_Mhage/statu…
— sn0w@株と為替とOWとeSPORTS (@oh_me_zzZ) Nov 19, 2018
浮動小数点演算って一般にあまり知られていないよね・・・。 twitter.com/Tw_Mhage/statu…
— まーく@器用貧乏系 (@markcsproj) Nov 19, 2018
これ、単純にプログラミングリテラシーの問題だと思うんだけど。。。 twitter.com/Tw_Mhage/statu…
— タカナシ© (@takanashi_nico) Nov 19, 2018
今の計算機屋のリテラシーってこんなもんなのか…… twitter.com/Tw_Mhage/statu…
— パピルス加藤/たまには外遊したいのう (@papyrus_kato) Nov 19, 2018
スポンサーリンク
スポンサーリンク
この記事に問題があると考えた場合、こちらから作者様にご連絡をお願いします。