浮動小数点数の比較(丸め誤差に注意)
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 : 同じ
訪問数 71 回, 今日の訪問数 1回




ディスカッション
コメント一覧
まだ、コメントがありません