浮動小数点数の比較(丸め誤差に注意)

2026年7月21日

広告

10進数を2進数に変換することにより、誤差が生じます。
プログラムで比較する場合、このことを考慮しないと同一値と判断されないことがあります。

テストコード

using System;
using UnityEngine;
public class FloatTest : MonoBehaviour
{
    void Start()
    {
        Func<int, float, bool> Check;
        Debug.Log("floatの誤差");
        Check = (i, f) => i == f * 10.0f;
        CompareCalc(Check);
        Debug.Log("floatの誤差(誤差の小ささで調整)");
        Check = (i, f) => Mathf.Abs(i - f * 10.0f) < 0.001f;
        CompareCalc(Check);
        Debug.Log("floatの誤差(Equalsメソッドでチェック)");
        Check = (i, f) => (f * 10.0f).Equals(i);
        CompareCalc(Check);
        Func<int, decimal, bool> CheckDeciaml;
        Debug.Log("floatの誤差(decimal型で比較)");
        CheckDeciaml = (i, d) => i == d * 10.0m;
        CompareCalc(CheckDeciaml);
        Debug.Log("floatの誤差(decimal型で比較(Equalsメソッドでチェック))");
        CheckDeciaml = (i, d) => (d * 10.0m).Equals(i);
        CompareCalc(CheckDeciaml);
    }
    /// <summary>
    /// 0から10までの整数を元に、float型で、10で割った結果を10倍して比較
    /// </summary>
    /// <param name="compareFunc">Compare func.</param>
    private static void CompareCalc(Func<int, float, bool> compareFunc)
    {
        float data = 0.0f;
        for (int i = 0; i < 10; i++)
        {
            string compare;
            if (compareFunc(i, data))
            {
                compare = "同じ";
            }
            else
            {
                compare = "違う";
            }
            Debug.Log(i + ":" + compare);
            data += 0.1f;
        }
        Debug.Log("");
    }
    /// <summary>
    /// 0から10までの整数を元に、decimal型で、10で割った結果を10倍して比較
    /// </summary>
    /// <param name="compareFunc">Compare func.</param>
    private static void CompareCalc(Func<int, decimal, bool> compareFunc)
    {
        decimal data = 0;
        for (int i = 0; i < 10; i++)
        {
            string compare;
            if (compareFunc(i, data))
            {
                compare = "同じ";
            }
            else
            {
                compare = "違う";
            }
            Debug.Log(i + ":" + compare);
            data += 0.1m;
        }
        Debug.Log("");
    }
}

テストコード(LINQ版)

using System;
using System.Linq;
using UnityEngine;
public class FloatTest : MonoBehaviour
{
    void Start()
    {
        Func<int, float, bool> Check;
        Debug.Log("floatの誤差");
        Check = (i, f) => i == f * 10.0f;
        CompareCalc(Check);
        Debug.Log("floatの誤差(誤差の小ささで調整)");
        Check = (i, f) => Mathf.Abs(i - f * 10.0f) < 0.001f;
        CompareCalc(Check);
        Debug.Log("floatの誤差(Equalsメソッドでチェック)");
        Check = (i, f) => (f * 10.0f).Equals(i);
        CompareCalc(Check);
        Func<int, decimal, bool> CheckDeciaml;
        Debug.Log("floatの誤差(decimal型で比較)");
        CheckDeciaml = (i, d) => i == d * 10.0m;
        CompareCalc(CheckDeciaml);
        Debug.Log("floatの誤差(decimal型で比較(Equalsメソッドでチェック))");
        CheckDeciaml = (i, d) => (d * 10.0m).Equals(i);
        CompareCalc(CheckDeciaml);
    }
    /// <summary>
    /// 0から10までの整数を元に、float型で、10で割った結果を10倍して比較
    /// </summary>
    /// <param name="compareFunc">Compare func.</param>
    private static void CompareCalc(Func<int, float, bool> compareFunc)
    {
        Enumerable.Range(0, 10).ToList().ForEach(i => Debug.Log(compareFunc(i, (float)i / 10) ? $"{i} : 同じ" : $"{i} : 違う"));
        Debug.Log("");
    }
    /// <summary>
    /// 0から10までの整数を元に、decimal型で、10で割った結果を10倍して比較
    /// </summary>
    /// <param name="compareFunc">Compare func.</param>
    private static void CompareCalc(Func<int, decimal, bool> compareFunc)
    {
        Enumerable.Range(0, 10).ToList().ForEach(i => Debug.Log(compareFunc(i, (decimal)i / 10) ? $"{i} : 同じ" : $"{i} : 違う"));
        Debug.Log("");
    }
}

実行結果

floatの誤差
0 : 同じ
1 : 違う
2 : 違う
3 : 違う
4 : 違う
5 : 同じ
6 : 違う
7 : 違う
8 : 違う
9 : 違う
floatの誤差(誤差の小ささで調整)
0 : 同じ
1 : 同じ
2 : 同じ
3 : 同じ
4 : 同じ
5 : 同じ
6 : 同じ
7 : 同じ
8 : 同じ
9 : 同じ
floatの誤差(Equalsメソッドでチェック)
0 : 同じ
1 : 同じ
2 : 同じ
3 : 同じ
4 : 同じ
5 : 同じ
6 : 同じ
7 : 同じ
8 : 同じ
9 : 同じ
floatの誤差(decimal型で比較)
0 : 同じ
1 : 同じ
2 : 同じ
3 : 同じ
4 : 同じ
5 : 同じ
6 : 同じ
7 : 同じ
8 : 同じ
9 : 同じ
floatの誤差(decimal型で比較(Equalsメソッドでチェック))
0 : 同じ
1 : 同じ
2 : 同じ
3 : 同じ
4 : 同じ
5 : 同じ
6 : 同じ
7 : 同じ
8 : 同じ
9 : 同じ
訪問数 208 回, 今日の訪問数 1回

広告

C#,Unity

Posted by hidepon