■ IEEE 754 배정도 실수 확장을 사용하는 방법을 보여준다.
▶ NumericExtension.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
using System; using System.Runtime.InteropServices; /// <summary> /// 숫자 확장 /// </summary> /// <remarks> /// 컨트롤에서 사용하는 숫자 유틸리티 메소드이다. /// 이러한 메소드는 범위가 WPF DoubleUtil 클래스와 유사하다. /// </remarks> public static class NumericExtensions { //////////////////////////////////////////////////////////////////////////////////////////////////// Structure ////////////////////////////////////////////////////////////////////////////////////////// Public #region 배정도 실수 공용체 - DoubleUnion /// <summary> /// 배정도 실수 공용체 /// </summary> /// <remarks> /// NanUnion은 double을 비트를 쉽게 조작할 수 있는 unsigned long으로 효율적으로 변환하는 데 사용되는 C++ 스타일 유형 공용체이다. /// </remarks> [StructLayout(LayoutKind.Explicit)] public struct DoubleUnion { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Public #region Field /// <summary> /// 실수 값 /// </summary> /// <remarks> /// 공용체의 부동 소수점 표현이다. /// </remarks> [FieldOffset(0)] public double FloatingValue; /// <summary> /// 정수 값 /// </summary> /// <remarks> /// 공용체의 정수 표현이다. /// </remarks> [FieldOffset(0)] public ulong IntegerValue; #endregion } #endregion //////////////////////////////////////////////////////////////////////////////////////////////////// Structure ////////////////////////////////////////////////////////////////////////////////////////// Public #region 0 여부 구하기 - IsZero(value) /// <summary> /// 0 여부 구하기 /// </summary> /// <param name="value">배정도 실수 값</param> /// <returns>0 여부</returns> public static bool IsZero(this double value) { return Math.Abs(value) < 2.2204460492503131E-15; } #endregion #region 비숫자 여부 구하기 - IsNaN(value) /// <summary> /// 비숫자 여부 구하기 /// </summary> /// <param name="value">값</param> /// <returns>비숫자 여부</returns> public static bool IsNaN(this double value) { DoubleUnion union = new DoubleUnion { FloatingValue = value }; // IEEE 754 배정밀도 부동 소수점 숫자는 지수가 2047이고 가수가 0이 아닌 경우 NaN이다. ulong exponent = union.IntegerValue & 0xfff0000000000000L; if((exponent != 0x7ff0000000000000L) && (exponent != 0xfff0000000000000L)) { return false; } ulong mantissa = union.IntegerValue & 0x000fffffffffffffL; return mantissa != 0L; } #endregion #region 두 숫자의 값이 비슷한지 여부 구하기 - AreClose(left, right) /// <summary> /// 두 숫자의 값이 비슷한지 여부 구하기 /// </summary> /// <param name="left">왼쪽 값</param> /// <param name="right">오른쪽 값</param> /// <returns>두 숫자의 값이 비슷한지 여부</returns> public static bool AreClose(double left, double right) { if(left == right) { return true; } double a = (Math.Abs(left) + Math.Abs(right) + 10.0) * 2.2204460492503131E-16; double b = left - right; return (-a < b) && (a > b); } #endregion #region 값 이상 여부 구하기 - IsGreaterThan(left, right) /// <summary> /// 값 이상 여부 구하기 /// </summary> /// <param name="left">왼쪽 값</param> /// <param name="right">오른쪽 값</param> /// <returns>값 이상 여부</returns> public static bool IsGreaterThan(double left, double right) { return (left > right) && !AreClose(left, right); } #endregion #region 값 이하 여부 구하기 - IsLessThanOrClose(left, right) /// <summary> /// 값 이하 여부 구하기 /// </summary> /// <param name="left">왼쪽 값</param> /// <param name="right">오른쪽 값</param> /// <returns>값 이하 여부</returns> public static bool IsLessThanOrClose(double left, double right) { return (left < right) || AreClose(left, right); } #endregion } |