LoginSignup
39
38

"「0.1+0.2≠0.3」だから浮動小数点数を扱うときには気を付けましょう" はいいんだけど結局どうしたらいいのかまでフォローしたほうが親切だと思ったので調べてみた

Posted at

釣られた

https://qiita.com/higashi_nc/items/9a5ea00415a008f06843 に釣られて読みました。

2行でまとめると以下のような内容です。

  1. 10進数の0.1や0.2は浮動小数点数で表すとピッタリ0.1や0.2にはならずに誤差が出る
  2. 浮動小数点数の扱いを理解して、より堅牢なプログラムを作成することを願っています。

え?結局どうしたらいいの?という感想だけ残ったので各言語での浮動小数点数同士の比較の方法を ChatGPT に教えてもらいました。

結局どうしたらいいのか

基本的に浮動小数点数同士の差がある程度の誤差より小さければ同じ数である、という判定をすればいいようです。
今回の回答には含まれませんでしたが、おそらく言語によっては浮動小数点数同士の比較をする専用のライブラリなどもあるかと思われます。

Python

import math

a = 0.1
b = 0.2

if math.isclose(a + b, 0.3, rel_tol=1e-5):
    print("等しい")
else:
    print("等しくない")

Go

package main

import (
    "fmt"
    "math"
)

// FloatEquals 浮動小数点数が等しいかどうかを判定する
func FloatEquals(a, b, epsilon float64) bool {
    return math.Abs(a - b) < epsilon
}

func main() {
    var a, b float64 = 0.1, 0.2
    var result float64 = a + b

    // 0.3 と比較する場合
    if FloatEquals(result, 0.3, 0.0001) {
        fmt.Println("等しい")
    } else {
        fmt.Println("等しくない")
    }
}

C

#include <stdio.h>
#include <math.h>

int floatEquals(double a, double b, double epsilon) {
    return fabs(a - b) < epsilon;
}

int main() {
    double a = 0.1;
    double b = 0.2;
    double epsilon = 0.00001;

    if (floatEquals(a + b, 0.3, epsilon)) {
        printf("等しい\n");
    } else {
        printf("等しくない\n");
    }

    return 0;
}

PHP

function floatEquals($a, $b, $epsilon = 0.00001) {
    return abs($a - $b) < $epsilon;
}

$a = 0.1;
$b = 0.2;

if (floatEquals($a + $b, 0.3)) {
    echo "等しい\n";
} else {
    echo "等しくない\n";
}

Java

public class Main {
    public static boolean floatEquals(double a, double b, double epsilon) {
        return Math.abs(a - b) < epsilon;
    }

    public static void main(String[] args) {
        double a = 0.1;
        double b = 0.2;
        double epsilon = 0.00001;

        if (floatEquals(a + b, 0.3, epsilon)) {
            System.out.println("等しい");
        } else {
            System.out.println("等しくない");
        }
    }
}

JavaScript

function floatEquals(a, b, epsilon = 0.00001) {
    return Math.abs(a - b) < epsilon;
}

let a = 0.1;
let b = 0.2;

if (floatEquals(a + b, 0.3)) {
    console.log("等しい");
} else {
    console.log("等しくない");
}
39
38
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
38