Skip to content

Commit f0422b8

Browse files
author
Oren (electricessence)
committed
Tweaks.
1 parent 36d5f31 commit f0422b8

4 files changed

Lines changed: 318 additions & 935 deletions

File tree

Numeric.cs

Lines changed: 2 additions & 210 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
*/
55

66
using System;
7-
using System.Globalization;
7+
using Open.Numeric.Precision;
88

99

1010
namespace Open.Numeric
1111
{
12-
public static class Extensions
12+
public static class Extensions
1313
{
1414
#region Numeric shortcuts.
1515
public static bool IsNaN(this double value)
@@ -30,214 +30,6 @@ public static bool IsDefault(this double value)
3030
}
3131
#endregion
3232

33-
34-
#region Precision Assurance.
35-
/// <summary>
36-
/// Accurate way to convert float to decimal by converting to string first. Avoids tolerance issues.
37-
/// </summary>
38-
public static decimal ToDecimal(this float value)
39-
{
40-
return decimal.Parse(value.ToString(CultureInfo.InvariantCulture));
41-
}
42-
43-
/// <summary>
44-
/// Shortcut for validating a if a floating point value is considered zero (within epsilon tolerance).
45-
/// </summary>
46-
public static bool IsZero(this float value)
47-
{
48-
return IsPreciseEqual(value, 0f);
49-
}
50-
51-
/// <summary>
52-
/// Shortcut for validating a if a double tolerance floating point value is considered zero (within epsilon tolerance).
53-
/// </summary>
54-
public static bool IsZero(this double value)
55-
{
56-
return IsPreciseEqual(value, 0d);
57-
}
58-
59-
60-
/// <summary>
61-
/// Shortcut for validating a if a double tolerance floating point value is considered zero (within epsilon tolerance).
62-
/// </summary>
63-
public static bool IsNearZero(this double value, double precision = 0.001)
64-
{
65-
return IsNearEqual(value, 0d, precision);
66-
}
67-
68-
/// <summary>
69-
/// Shortcut for returning true zero if a double tolerance floating point value is considered zero (within epsilon tolerance).
70-
/// </summary>
71-
public static double FixZero(this double value)
72-
{
73-
return !value.Equals(0) && value.IsZero() ? 0 : value;
74-
}
75-
76-
static double ReturnZeroIfFinite(this float value)
77-
{
78-
if (float.IsNegativeInfinity(value))
79-
return double.NegativeInfinity;
80-
if (float.IsPositiveInfinity(value))
81-
return double.PositiveInfinity;
82-
83-
return float.IsNaN(value) ? double.NaN : 0D;
84-
}
85-
86-
/// <summary>
87-
/// Returns the number of decimal places before last zero digit.
88-
/// </summary>
89-
public static int DecimalPlaces(this double source)
90-
{
91-
if (source.IsNaN())
92-
return 0;
93-
94-
string valueString = source.ToString();
95-
var index = valueString.IndexOf('.');
96-
return index == -1 ? 0 : valueString.Length - index - 1;
97-
}
98-
99-
100-
101-
102-
/// <summary>
103-
/// Shortcut for validating a if a floating point value is close enough to another addValue using the given tolerance tolerance.
104-
/// </summary>
105-
public static bool IsNearEqual(this float a, float b, float tolerance)
106-
{
107-
return a.Equals(b) || float.IsNaN(a) && float.IsNaN(b) || Math.Abs(a - b) < tolerance;
108-
}
109-
110-
/// <summary>
111-
/// Shortcut for validating a if a double precision floating point value is close enough to another addValue using the given tolerance tolerance.
112-
/// </summary>
113-
public static bool IsNearEqual(this double a, double b, double tolerance)
114-
{
115-
return a.Equals(b) || double.IsNaN(a) && double.IsNaN(b) || Math.Abs(a - b) < tolerance;
116-
}
117-
118-
/// <summary>
119-
/// Shortcut for validating a if a decimal addValue is close enough to another addValue using the given tolerance tolerance.
120-
/// </summary>
121-
public static bool IsNearEqual(this decimal a, decimal b, decimal tolerance)
122-
{
123-
return a.Equals(b) || Math.Abs(a - b) < tolerance;
124-
}
125-
126-
/// <summary>
127-
/// Shortcut for validating a if a decimal addValue is close enough to another addValue using the given tolerance tolerance.
128-
/// </summary>
129-
public static bool IsRelativeNearEqual(this double a, double b, uint minDecimalPlaces)
130-
{
131-
var tolerance = 1/Math.Pow(10,minDecimalPlaces);
132-
if(a.IsNearEqual(b,tolerance)) return true;
133-
if(double.IsNaN(a) || double.IsNaN(b)) return false;
134-
var d = Math.Min(a.DecimalPlaces(),b.DecimalPlaces());
135-
var divisor = Math.Pow(10,minDecimalPlaces-d);
136-
a /= divisor;
137-
b /= divisor;
138-
return a.IsNearEqual(b,tolerance);
139-
}
140-
141-
/// <summary>
142-
/// Validates if values are equal within epsilon tolerance.
143-
/// </summary>
144-
public static bool IsPreciseEqual(this double a, double b, bool stringValidate = false)
145-
{
146-
return IsNearEqual(a, b, double.Epsilon) || (stringValidate && !double.IsNaN(a) && !double.IsNaN(b) && a.ToString() == b.ToString());
147-
}
148-
149-
150-
/// <summary>
151-
/// Validates if values are equal within epsilon tolerance.
152-
/// </summary>
153-
public static bool IsPreciseEqual(this float a, float b, bool stringValidate = false)
154-
{
155-
return IsNearEqual(a, b, float.Epsilon) || (stringValidate && !float.IsNaN(a) && !float.IsNaN(b) && a.ToString() == b.ToString());
156-
}
157-
158-
/// <summary>
159-
/// Validates if values are equal within epsilon tolerance.
160-
/// </summary>
161-
public static bool IsPreciseEqual(this double? a, double? b, bool stringValidate = false)
162-
{
163-
return !a.HasValue && !b.HasValue || a.HasValue && b.HasValue && a.Value.IsPreciseEqual(b.Value, stringValidate);
164-
}
165-
166-
/// <summary>
167-
/// Validates if values are equal within epsilon tolerance.
168-
/// </summary>
169-
public static bool IsPreciseEqual(this float? a, float? b, bool stringValidate = false)
170-
{
171-
return !a.HasValue && !b.HasValue || a.HasValue && b.HasValue && a.Value.IsPreciseEqual(b.Value, stringValidate);
172-
}
173-
174-
175-
176-
/// <summary>
177-
/// Shortcut for validating a if a potential floating pointvalue is close enough to another addValue using the given tolerance tolerance.
178-
/// </summary>
179-
public static bool IsNearEqual(this IComparable a, IComparable b, double tolerance)
180-
{
181-
if(a==null)
182-
throw new NullReferenceException();
183-
if(b==null)
184-
throw new ArgumentNullException("b");
185-
186-
if (a is float)
187-
return ((float)a).IsNearEqual((float)b, tolerance);
188-
if (a is double)
189-
return ((double)a).IsNearEqual((double)b, tolerance);
190-
if (a is decimal)
191-
return ((decimal)a).IsNearEqual((decimal)b, tolerance);
192-
193-
throw new InvalidCastException();
194-
}
195-
196-
197-
/// <summary>
198-
/// Accurate way to convert float to double by rounding finite values to a decimal point tolerance level.
199-
/// </summary>
200-
public static double ToDouble(this float value, int precision)
201-
{
202-
if (precision < 0 || precision > 15)
203-
throw new ArgumentOutOfRangeException("precision", precision, "Must be bewteen 0 and 15.");
204-
205-
double result = value.ReturnZeroIfFinite();
206-
// ReSharper disable RedundantCast
207-
return result.IsZero() ? Math.Round((double)value, precision) : result;
208-
// ReSharper restore RedundantCast
209-
}
210-
211-
/// <summary>
212-
/// Accurate way to convert float to double by converting to string first. Avoids tolerance issues.
213-
/// </summary>
214-
public static double ToDouble(this float value)
215-
{
216-
double result = value.ReturnZeroIfFinite();
217-
return result.IsZero() ? double.Parse(value.ToString(CultureInfo.InvariantCulture)) : result;
218-
}
219-
220-
/// <summary>
221-
/// Accurate way to convert possible float to double by converting to string first. Avoids tolerance issues.
222-
/// </summary>
223-
public static double ToDouble(this float? value)
224-
{
225-
return value.HasValue ? value.Value.ToDouble() : double.NaN;
226-
}
227-
228-
229-
/// <summary>
230-
/// Accurate way to convert a possible float to double by rounding finite values to a decimal point tolerance level.
231-
/// </summary>
232-
/// <param name="tolerance"></param>
233-
public static double ToDouble(this float? value, int precision)
234-
{
235-
if (precision < 0 || precision > 15)
236-
throw new ArgumentOutOfRangeException("precision", precision, "Must be bewteen 0 and 15.");
237-
return value.HasValue ? value.Value.ToDouble(precision) : double.NaN;
238-
}
239-
240-
#endregion
24133
}
24234

24335
public static class NumericConvert

0 commit comments

Comments
 (0)