[[20171203152458]] 『引き算結果がおかしくなる』(X) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『引き算結果がおかしくなる』(X)

普通に
A1のセルに 0.1419656 を入力
A2のセルに 0.1415  を入力

A3に数式で =A1-A2 と入力すると

0.0004656

とでるのですが、
セルの小数点以下を増やしていくと

0.0004656000000000100

と、小数点以下17桁になぞの「1」が登場します。

これはどんな現象なのでしょうか?

< 使用 Excel:Excel2013、使用 OS:Windows10 >


浮動小数点誤差の話です。
ここのサイトで全文検索をかけると
参考記事が得られます。
(γ) 2017/12/03(日) 15:38

 最近、「浮動小数点誤差」と言う言葉が目に付いているんですけど、
 以前は、「小数演算誤差」だったです。

 「小数演算誤差」は言葉としては、現象を表現しているだけで、誤差の根源的な意味は含まれていない。

 けど、無難な表現でもありました。

 ところが、「浮動小数点誤差」は根源的な意味を少し入れようとしている様に感じます。
 つまり「浮動・・」なんだからと言うニュアンスがあります。

 実際、ネット検索したら、
 「固定小数点の場合は非常に大きな数値や非常に小さな数値は扱えませんが計算では誤差が発生する事は有りません。」
 なんて言い切っている"識者"もいた。

 でも私は「固定小数点」だって誤差はあるんじゃないかと思っています。

 根源的な理由は小数点がふらふら動くことじゃなく、
 単に10進小数を2進数で管理しようとしているからに過ぎないと思っています。

 γさん
  気が向いたらで結構ですが、この辺りの蘊蓄をお聞かせ頂けないでしょうか?

(半平太) 2017/12/03(日) 16:44


  >これはどんな現象なのでしょうか?

  (1)A3の値の2進ビットイメージ    +0.000000000001111010000011011110001100010111100100011111
  (2)手入力「0.0004656」のイメージ  +0.0000000000011110100000110111100011000101111001000111101100111111
                                               ↑
                                              ここに注目

  つまりA3は、手入力の「0.0004656」よりほんの僅か大きいんです。

  何故そんなことが起きたかと言うと、
  A3の計算の元値(二つ)に共通の「0.1415?」と言う部分が有り、
  その部分を認識するために有効ビットの一部が消費されています。

  この為、それ以下の小数部分の認識に使えるビット数がかなり減る。→精度が落ちる。

  一方、手入力は、有効ビット全て使えます。

  精度の高い小数は、純粋(※)な 0.0004656と表示されますが、
 A3の値は精度がそれ程高くないので、質問にあった様な1が余分に出たという訳です。

 ※純粋と表現しましたが、真の0.0004656ではありません。
 2進数では正確に把握し得ないですからね。
 じゃ、「演算」なんかしなくたって誤差はあるじゃないかと思うでしょうが、
 まったくその通りです。

 でも、真の値が何かを判別する物差しがPCに無いんですから、どうしようもないです。
 つまり、演算しない限り、単体で手入力した小数の(真値との)誤差なんて認識できないんです。

 なので「小数演算誤差」と呼ぶのが無難と私は思います。
 逆に「浮動小数点誤差」には肝心の「演算」ファクターが抜けています。

(半平太) 2017/12/03(日) 20:40


Excelも他の多くの言語と同じく、
浮動小数点数算術標準 IEEE754(Standard for Floating-Point Arithmetic)に
準拠しているのですが、
こうした規格との関係を念頭に、総称してそのように呼んだものです。
 
そのうえで、ネット上のまとまったドキュメントを読まれるのがよいですよ、
と申し上げました。
こちらの掲示板の検索でもヒットします。
例えば、
http://www.excel.studio-kazu.jp/kw/20170603163449.html
で私が引用した下記の芳坂氏の雑誌記事がよくまとまっていると思います。
IEEE754の概要、誤差への対応方法など(特に後者がユーザーには重要)。
 
> 演算誤差によるものでしょう。

http://qiita.com/Q11Q/items/84b380b20ef51eca929c
> にある雑誌記事がよくまとまっていると思います。
> このテーマの定番記事と言って良いでしょう。
> 参考にしてください。
 
# ちなみに、ご指摘のありました用語の件ですが、
# 演算誤差とか丸め誤差とか、単に誤差とも言うと思います。
# こちらの掲示板での使い方の伝統は知りませんでした。
# その差異に余り力点を置く必要もないかと私は思います。

(γ) 2017/12/04(月) 07:19


横から & 後出し で失礼します。
なおかつ、釈迦に説法で恐縮ですが...

固定小数点というのは、整数を表す方法で、正体としては2進数そのもの、いわゆるバイナリと呼ばれていた?ものです。(小数点なんて名前が迷わせているようですが)
そこで使用する領域は、2バイト、4バイト、8バイト=16ビット、32ビット、64ビットですが、正の数と負の数を表すために、実際には各々15ビット、31ビット、63ビットが数字の絶対値として使えます。先頭の1ビットは0が正、1が負を表します。
10^X=2^15(^はべき乗)から、X=15*0.3=4.5桁≒4桁(正確には32768)まで表現可能です。なお、ここで0.3≒log2(常用対数)です。
同様に
10^X=2^31から、X=31*0.3=9.3桁≒9桁
10^X=2^63から、X=63*0.3=18.9桁≒18桁までは正確に表現できます。
ところが、桁数が18桁(最大値)を超えたり、小数点がついてくると、固定小数点では対応が出来ません。

そこで浮動小数点が登場します。これは固定小数点とは全く異なった概念です。
符号(1ビット)*指数(位取り)*仮数(実際の値を近似値で表す)という形式で表現されています。 かつ、指数部は、固定小数点の正負と同じ様に、+(整数部)も−(小数点以下)も表せるように、ちょうど半分で分けて使います。
半精度浮動小数点数では、符号部 1 ビット ・ 指数部 5 ビット ・ 仮数部 10 ビット
単精度浮動小数点数では、符号部 1 ビット ・ 指数部 8 ビット ・ 仮数部 23 ビット
倍精度浮動小数点数では、符号部 1 ビット ・ 指数部 11 ビット ・ 仮数部 52 ビット
四倍精度浮動小数点数では、符号部 1 ビット ・ 指数部 15 ビット ・ 仮数部 112 ビット
だそうで、
半精度の場合: (-1) 符号部×2^(指数部 ‐15) ×(1+仮数部)
単精度の場合: (-1) 符号部×2^(指数部 ‐127) ×(1+仮数部)
倍精度の場合: (-1) 符号部×2^(指数部 ‐1023)×(1+仮数部)
四倍精度の場合: (-1) 符号部×2^(指数部 ‐16383)×(1+仮数部)
の表現が可能です。もちろん、この指数部、仮数部を超える様な表現はできません。
で、1+仮数部が値の部分ですが、最大で2^112=10^Xと置いてXを求めると、
整数から小数点以下の桁数の合計が、X=0.3*112=33.6桁≒33で10進の33桁桁までは表現可能となります。
とは言え、これで全部をカバーできないのが、2進数の辛いところで、33けたではカバーできない数字が存在します。
  例えば0,1(10)=(0.000110・・・)(2)
   =0*1/(2^1)+0*1/(2^2)+0*1/(2^3)+1*1/(2^4)+1*1/(2^5)+0*1/(2^6)+・・・    となりぴったり表現できないことが殆どです。
たまに0.5(10)=0.1(2)や0.25(10)=0.01(2)など、1を2のべき乗で割った数字の場合はきっちり値が求まることもあります。
で、殆どの場合、ビットの最後の部分(最大で113ビット目以降)で誤差が出ます。それは2進数と10進数の関係上致し方ないことですし、かつコンピュータの計算上の使用できるビット数にも制限があることから、止むを得ないものです。
特にエクセルの場合は、何バイトの浮動小数点を使っているのかも、エクセルの自動判断ですから、不明ですし、誤差は出るものと覚悟するしか無いようです。
 浮動小数点の場合、もとの値を浮動小数点においた時点で誤差が出ていますし、それを使って演算すれば、当然誤差が出てきます。結果については、有効桁数を考えに入れて誤差部分を丸めて表現することになります。
そういう考え方から導かれていますので、非常に大きな小数点付きの値と、非常に小数点の小さい値の演算は下手をすると、演算の精度が落ちてしまうことも考えられます。
 ただ、普通(?)の演算範囲では、ほとんど問題なく使用できる、ということで使っています。

(パオ〜〜ンx) 2017/12/05(火) 11:22


 >固定小数点というのは、整数を表す方法

 勉強不足(と言うか無勉強)で済みません。
 それ、知らなかったです。お恥ずかしい。

 γさん、パオ〜〜ンxさん、有難うございました。m(__)m

(半平太) 2017/12/05(火) 15:13


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.