Upgrade to Pro — share decks privately, control downloads, hide ads and more …

【基本情報対策】浮動小数点と誤差

 【基本情報対策】浮動小数点と誤差

Avatar for 赤神青空

赤神青空 PRO

October 13, 2026

Video

More Decks by 赤神青空

Other Decks in Programming

Transcript

  1. ▪赤は16進数の 前回のクイズの答えは「B」 80 で、8×16+0=128 前回のクイズ カラーコード #80FF の、 R(⾚)の値を10進数にすると? #

    FF は、⾚ 80‧緑 FF‧⻘ 00。 16進数の 80 は、上の桁が16の重み A 16進数のまま読んだもの B 8×16+0=128 C 緑の FF の値 答えは B 今ココ おさらい D 上の桁だけを⾒たもの 2/16
  2. ▪2進数の小数・浮動小数点・誤差 今回の話 ① 2進数の⼩数 0.1は割り切れない ② 浮動⼩数点 符号部‧指数部‧仮数部 ③ 誤差と実務

    0.1+0.2‧⾦額‧⽐較 今回いちばん持ち帰ってほしいこと 0.1は2進数で割り切れないので、⼩数の計算には誤差が出ることがある 今ココ はじめに 3/16
  3. ▪小数点の右は 2進数の小数にも、桁の重みがある 1/2・1/4・1/8 … 1の位 . ⼩数第1位 ⼩数第2位 ⼩数第3位 ⼩数第4位

    = 0.5 = 0.25 = 0.125 = 0.0625 / / / / ⼩数点の右は、重みが 1/2 ずつ⼩さくなる 2進数の 0.1 2進数の 0.01 2進数の 0.11 = 0.5 = 0.25 = 0.75 = 1/2 今ココ 2進数の小数 = 1/4 = 1/2 + 1/4 4/16
  4. ▪2倍して、整数部を上から読む 小数を2進数にする 2倍して、整数部を書く . × 2 = . 整数部 .

    × 2 = . 整数部 整数部 . ×2= ⼩数部が 0 になったら終わり 今ココ 2進数の小数 0.625 を2進数にすると 上から読む . 確かめ:0.5 + 0 + 0.125 = 0.625 5/16
  5. ▪0.0001100110011…と、0011がくり返す 0.1は2進数で割り切れない . ×2= . ×2= . ×2= . ×2=

    . ×2= . ×2= . 整数部 . 整数部 . 整数部 . 整数部 . 整数部 . 整数部 …(ここから、くり返す) 今ココ 2進数の小数 0.1 を2進数にすると . 0.2 に戻る … 0011 がくり返して、終わらない 10進数でも 1/3 = 0.333… は 終わらない。2進数で終わるのは、 約分した分⺟が 2‧4‧8 … の ときだけ(0.1 は 1/10) 6/16
  6. ▪小数点の位置を決めておくか、指数で動かすか 固定小数点と浮動小数点 固定⼩数点数 ⼩数点の位置を、あらかじめ決めておく 整数部 4ビット . ⼩数部 4ビット 浮動⼩数点数

    ⼩数点の位置を、指数で動かす 1.01011 × 2 仮数 3 指数 = 8 + 2 + 0.5 + 0.25 = 10.75 = 1010.11 = 10.75 この例なら、1/16 刻みで 15.9375 まで 範囲と細かさが、最初に決まる 10進数の 6.02 × 10²³ と同じ書き⽅ ⼤きな数も⼩さな数も、同じビット数で 今ココ 浮動小数点 7/16
  7. ▪符号部・指数部・仮数部に分けて持つ(IEEE 浮動小数点の形 754) 値 = ±1.(仮数部)× 2(指数部 − 127) 単精度の場合。仮数部には「1.」の後ろだけを⼊れ、指数部には指数に127を⾜した数を⼊れる

    単精度(32ビット) 符号部 1ビット 指数部 8ビット 倍精度(64ビット) 符号部 1ビット 指数部 11ビット 仮数部 23ビット 仮数部 52ビット 倍精度は、指数に1023を⾜した数を指数部に⼊れる。JavaScript の Number は倍精度 今ココ 浮動小数点 8/16
  8. ▪仮数部の23ビットに収まらない分は、丸める 0.1を単精度で表すと 0.1 = 1.6 × 2−4 (1.6 は2進数で 1.1001

    1001 1001 …) 指数部 123(123 − 127 = −4) 符号部 0 仮数部(1.6 の「1.」の後ろ) 本当は 1001 1001 1001 … と終わらない 23ビットに収まるように、近い⽅へ丸める(この例では切り上げで、最後の 0 が 1 になる) ⼊っている値:0.100000001490116… 0.1 との差が、丸め誤差 今ココ 浮動小数点 9/16
  9. ▪桁数に収める誤差と、計算を途中で止める誤差 丸め誤差と打切り誤差 丸め誤差 表せる桁数に収めるため、 端数を丸めて⽣じる誤差 無限に続く計算を、 途中で打ち切って⽣じる誤差 0.1 を倍精度で表すと e=

    + / !+ / !+ / !+ 0.1 に⼀番近い値で代わりにする 本当の値は 2.718… 0.1000000000000000055… 0.1 + 0.2 のずれも、これが元 今ココ 誤差 打切り誤差 4項で⽌めると 2.666… 項を増やすほど、誤差は⼩さくなる 10/16
  10. ▪引き算と足し算で起きる誤差 桁落ちと情報落ち 桁落ち 値が近い数どうしの引き算で、 有効数字の桁が減る 1.2345 − 1.2344 = 0.0001

    有効数字は 5桁 → 1桁 対策:式を変形して、近い数の引き算を避ける 今ココ 誤差 情報落ち 絶対値の⼤きな数と⼩さな数の⾜し算で、 ⼩さな数の下の桁の⼀部か全部が、結果に残らない 倍精度で計算すると 10000000000000000 + 1 = 10000000000000000 対策:多数の数を⾜すときは、⼩さい数から⾜す 11/16
  11. ▪JavaScript0.1+0.2は0.3にならない の Number は倍精度 JavaScript で計算すると 中に⼊っている値(倍精度) 0.1 0.1000000000000000055… 0.30000000000000004

    0.2 0.2000000000000000111… > 0.1 + 0.2 === 0.3 0.1 + 0.2 0.3000000000000000444… 0.3 0.2999999999999999888… > 0.1 + 0.2 false Python で 0.1 + 0.2 を表⽰しても同じ 今ココ 実務では 12/16
  12. ▪浮動小数点数のまま足し引きしない 金額は整数か10進数型で持つ 整数で持つ 円やセントなど、扱う最⼩の単位の整数にする $0.10 + $0.20 セントにする 10 +

    20 = 30(セント) 整数の⾜し引きは、表せる範囲に収まるなら 誤差が出ない。表⽰するときにドルの形に直す 今ココ 実務では 10進数型を使う 10進数のまま計算する型を使う Decimal('0.1') + Decimal('0.2') → Decimal('0.3') Python の decimal で計算した例 Python の Decimal、Java の BigDecimal データベースの DECIMAL 型 13/16
  13. ▪差が十分に小さければ、同じとみなす 比較は誤差を許して行う === でそのまま⽐べる 0.1 + 0.2 === 0.3 //

    false わずかなずれでも、違う値として扱われる 差が⼗分に⼩さいかで⽐べる Math.abs(a - b) < 1e-9 math.isclose(0.1 + 0.2, 0.3) # True(Python) 許す幅は、扱う値の⼤きさに合わせて決める 今ココ 実務では 14/16