csharp.lang.correctness.double.double-epsilon-equality.correctness-double-epsilon-equality
semgrep
Author
unknown
Download Count*
License
Double.Epsilon is defined by .NET as the smallest value that can be added to or subtracted from a zero-value Double. It is unsuitable for equality comparisons of non-zero Double values. Furthermore, the value of Double.Epsilon is framework and processor architecture dependent. Wherever possible, developers should prefer the framework Equals() method over custom equality implementations.
Run Locally
Run in CI
Defintion
rules:
- id: correctness-double-epsilon-equality
patterns:
- pattern: |
$V1 - $V2
- pattern-either:
- pattern-inside: |
... <= Double.Epsilon
- pattern-inside: |
Double.Epsilon <= ...
- pattern-not-inside: |
double $V1 = 0;
...
- pattern-not-inside: |
double $V2 = 0;
...
- pattern-not-inside: |
$V1 = 0;
...
- pattern-not-inside: |
$V2 = 0;
...
message: Double.Epsilon is defined by .NET as the smallest value that can be
added to or subtracted from a zero-value Double. It is unsuitable for
equality comparisons of non-zero Double values. Furthermore, the value of
Double.Epsilon is framework and processor architecture dependent. Wherever
possible, developers should prefer the framework Equals() method over
custom equality implementations.
languages:
- csharp
severity: WARNING
metadata:
references:
- https://docs.microsoft.com/en-us/dotnet/api/system.double?view=net-6.0#testing-for-equality
- https://docs.microsoft.com/en-us/dotnet/api/system.double.epsilon?view=net-6.0#platform-notes
category: correctness
technology:
- .net
confidence: MEDIUM
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
Examples
double-epsilon-equality.cs
using System;
public class Example
{
static bool IsApproximatelyEqual(double value1, double value2, double epsilon)
{
// If they are equal anyway, just return True.
if (value1.Equals(value2))
return true;
// Handle NaN, Infinity.
if (Double.IsInfinity(value1) | Double.IsNaN(value1))
return value1.Equals(value2);
else if (Double.IsInfinity(value2) | Double.IsNaN(value2))
return value1.Equals(value2);
// Handle zero to avoid division by zero
double divisor = Math.Max(value1, value2);
if (divisor.Equals(0))
divisor = Math.Min(value1, value2);
//ruleid: correctness-double-epsilon-equality
return Math.Abs((value1 - value2) / divisor) <= Double.Epsilon;
}
static bool lazyEqualLeftCompare(double v1, double v2){
//ruleid: correctness-double-epsilon-equality
return Math.Abs(v1 - v2) <= Double.Epsilon;
}
static bool lazyEqualRightCompare(double v1, double v2){
//ruleid: correctness-double-epsilon-equality
return Double.Epsilon <= Math.Abs(v1 - v2);
}
static bool uselessZeroEqual(){
double v1 = 0;
double v2 = 0;
//ok
return Math.Abs(v1 - v2) <= Double.Epsilon;
}
static bool isZero(double arg){
double zero = 0;
//ok
return Math.Abs(arg - zero) <= Double.Epsilon;
}
static bool isZero2(double arg){
double zero = 0;
//ok
return Math.Abs(zero - arg) <= Double.Epsilon;
}
static bool isZero3(double arg){
double zero;
zero = 0;
//ok
return Math.Abs(zero - arg) <= Double.Epsilon;
}
static bool isZero4(double arg){
double zero;
zero = 0;
//ok
return Math.Abs(arg - zero) <= Double.Epsilon;
}
}
Short Link: https://sg.run/p9dZ