私はC++のバックグラウンドから来ましたが、フロートを同等に正確に比較できないことを知っています。 C#の場合、10進数値、または一般的な浮動小数点値に同じポリシーが適用されると単純に仮定しました。
基本的に、2つの10進数値があり、それらが互いに等しくない場合、何らかのアクションを実行する必要があります。例えば。:
decimal value1, value2;
// Assume value1 and value2 are set somewhere to valid values.
if( value1 != value2 )
{
// Do something
}
これが期待どおりに機能しない場合は、.00001などのようなエラーのマージンと同等の比較を行うソリューションを受け入れます。この問題の推奨される解決策は何ですか?
コードは期待どおりに機能します。 C#decimal
sは、基数10の数値を非常に正確に表現するように最適化されているため、比較している場合(金額など)、すべて正常です。
Jon Skeetによる小数の精度に関する非常に明確な説明を次に示します。
私は似たようなことを調査していましたが、エラーのマージンではなく精度で、Floatの拡張機能を作成することになりました。ただし、これはどのタイプにも簡単に適用できます。一連の複雑な比較があり、これにより見やすくなりました。
/// <summary>
/// A set of extensions to allow the convenient comparison of float values based on a given precision.
/// </summary>
public static class FloatingPointExtensions
{
/// <summary>
/// Determines if the float value is less than or equal to the float parameter according to the defined precision.
/// </summary>
/// <param name="float1">The float1.</param>
/// <param name="float2">The float2.</param>
/// <param name="precision">The precision. The number of digits after the decimal that will be considered when comparing.</param>
/// <returns></returns>
public static bool LessThan(this float float1, float float2, int precision)
{
return (System.Math.Round(float1 - float2, precision) < 0);
}
/// <summary>
/// Determines if the float value is less than or equal to the float parameter according to the defined precision.
/// </summary>
/// <param name="float1">The float1.</param>
/// <param name="float2">The float2.</param>
/// <param name="precision">The precision. The number of digits after the decimal that will be considered when comparing.</param>
/// <returns></returns>
public static bool LessThanOrEqualTo(this float float1, float float2, int precision)
{
return (System.Math.Round(float1 - float2, precision) <= 0);
}
/// <summary>
/// Determines if the float value is greater than (>) the float parameter according to the defined precision.
/// </summary>
/// <param name="float1">The float1.</param>
/// <param name="float2">The float2.</param>
/// <param name="precision">The precision. The number of digits after the decimal that will be considered when comparing.</param>
/// <returns></returns>
public static bool GreaterThan(this float float1, float float2, int precision)
{
return (System.Math.Round(float1 - float2, precision) > 0);
}
/// <summary>
/// Determines if the float value is greater than or equal to (>=) the float parameter according to the defined precision.
/// </summary>
/// <param name="float1">The float1.</param>
/// <param name="float2">The float2.</param>
/// <param name="precision">The precision. The number of digits after the decimal that will be considered when comparing.</param>
/// <returns></returns>
public static bool GreaterThanOrEqualTo(this float float1, float float2, int precision)
{
return (System.Math.Round(float1 - float2, precision) >= 0);
}
/// <summary>
/// Determines if the float value is equal to (==) the float parameter according to the defined precision.
/// </summary>
/// <param name="float1">The float1.</param>
/// <param name="float2">The float2.</param>
/// <param name="precision">The precision. The number of digits after the decimal that will be considered when comparing.</param>
/// <returns></returns>
public static bool AlmostEquals(this float float1, float float2, int precision)
{
return (System.Math.Round(float1 - float2, precision) == 0);
}
}
私は他の答えに同意しますが、1つの「本物の」サーバー側の小数がJSON /ブラウザから来るものと比較されるという問題に遭遇します(そしてある時点でフロートであったに違いありません)。
私はこのコードで小数点以下2桁までになりましたが、私の場合は十分に正確でした:
if (Decimal.Round(serverTotalPrice, 2) != Decimal.Round(request.TotalPrice, 2)) {
throw new ArgumentException("The submitted Total Price is not valid");
}