44 */
55
66using System ;
7- using System . Globalization ;
7+ using Open . Numeric . Precision ;
88
99
1010namespace 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