You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

281 lines
10 KiB

  1. using Apewer.Internals;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Runtime.InteropServices;
  5. using System.Text;
  6. namespace Apewer
  7. {
  8. /// <summary>数值实用工具。</summary>
  9. public static class NumberUtility
  10. {
  11. #region 随机数。
  12. /// <summary>用于生成随机数的时钟位置。</summary>
  13. private static int RandomSeed = 327680;
  14. private static float RandomTimer()
  15. {
  16. var now = DateTime.Now;
  17. return (float)((double)(checked((60 * now.Hour + now.Minute) * 60 + now.Second)) + (double)now.Millisecond / 1000.0);
  18. }
  19. private static void RandomInit()
  20. {
  21. float timer = RandomTimer();
  22. int num1 = RandomSeed;
  23. int num2 = BitConverter.ToInt32(BitConverter.GetBytes(timer), 0);
  24. num2 = ((num2 & 65535) ^ num2 >> 16) << 8;
  25. num1 = ((num1 & -16776961) | num2);
  26. RandomSeed = num1;
  27. }
  28. /// <summary>生成不大于 1 的随机数,最小为 0。</summary>
  29. public static float RandomFloat(float max = 1F)
  30. {
  31. RandomInit();
  32. int num1 = RandomSeed;
  33. if ((double)max != 0.0)
  34. {
  35. if ((double)max < 0.0)
  36. {
  37. num1 = BitConverter.ToInt32(BitConverter.GetBytes(max), 0);
  38. long vnum2 = (long)num1;
  39. vnum2 &= unchecked((long)((ulong)-1));
  40. num1 = checked((int)(vnum2 + (vnum2 >> 24) & 16777215L));
  41. }
  42. num1 = checked((int)(unchecked((long)num1) * 1140671485L + 12820163L & 16777215L));
  43. }
  44. RandomSeed = num1;
  45. return (float)num1 / 16777216f;
  46. }
  47. /// <summary>生成随机整数,包含最小值和最大值。</summary>
  48. /// <param name="min">最小值。</param>
  49. /// <param name="max">最大值。</param>
  50. /// <returns></returns>
  51. public static int RandomInteger(int max, int min = 0)
  52. {
  53. if (max < min)
  54. {
  55. var temp = max;
  56. max = min;
  57. min = temp;
  58. }
  59. float rate = (max - min + 1) * RandomFloat();
  60. int result = min + (int)rate;
  61. return result;
  62. }
  63. #endregion
  64. #region Restrict 约束值范围。
  65. /// <summary>约束值范围,若源值不在范围中,则修改为接近的值。</summary>
  66. public static T RestrictValue<T>(T origin, T min, T max) where T : IComparable
  67. {
  68. try
  69. {
  70. if (min.CompareTo(max) > 0) return origin;
  71. if (origin.CompareTo(min) < 0) return min;
  72. if (origin.CompareTo(max) > 0) return max;
  73. return origin;
  74. }
  75. catch { }
  76. return origin;
  77. }
  78. /// <summary>约束值范围,若源值不在范围中,则修改为接近的值。</summary>
  79. public static Byte RestrictValue(Byte target, Byte min, Byte max)
  80. {
  81. return RestrictValue<Byte>(target, min, max);
  82. }
  83. /// <summary>约束值范围,若源值不在范围中,则修改为接近的值。</summary>
  84. public static Int16 RestrictValue(Int16 target, Int16 min, Int16 max)
  85. {
  86. return RestrictValue<Int16>(target, min, max);
  87. }
  88. /// <summary>约束值范围,若源值不在范围中,则修改为接近的值。</summary>
  89. public static Int32 RestrictValue(Int32 target, Int32 min, Int32 max)
  90. {
  91. return RestrictValue<Int32>(target, min, max);
  92. }
  93. /// <summary>约束值范围,若源值不在范围中,则修改为接近的值。</summary>
  94. public static Int64 RestrictValue(Int64 target, Int64 min, Int64 max)
  95. {
  96. return RestrictValue<Int64>(target, min, max);
  97. }
  98. /// <summary>约束值范围,若源值不在范围中,则修改为接近的值。</summary>
  99. public static Single RestrictValue(Single target, Single min, Single max)
  100. {
  101. return RestrictValue<Single>(target, min, max);
  102. }
  103. /// <summary>约束值范围,若源值不在范围中,则修改为接近的值。</summary>
  104. public static Double RestrictValue(Double target, Double min, Double max)
  105. {
  106. return RestrictValue<Double>(target, min, max);
  107. }
  108. /// <summary>约束值范围,若源值不在范围中,则修改为接近的值。</summary>
  109. public static Decimal RestrictValue(Decimal target, Decimal min, Decimal max)
  110. {
  111. return RestrictValue<Decimal>(target, min, max);
  112. }
  113. #endregion
  114. /// <summary>平均值。</summary>
  115. public static double Average(params double[] values)
  116. {
  117. var amount = 0d;
  118. foreach (var i in values) amount += i;
  119. return amount / Convert.ToDouble(values.Length);
  120. }
  121. #region 最小值、最大值。
  122. private static T GetMost<T>(Func<T, T, bool> replace, T[] values)
  123. {
  124. if (values == null) return default;
  125. var length = values.LongLength;
  126. if (length == 0L) return default;
  127. if (length == 1L) return values[0L];
  128. var most = values[0];
  129. for (var i = 1L; i < length; i++)
  130. {
  131. var value = values[i];
  132. if (value == null) continue;
  133. if (most == null)
  134. {
  135. most = value;
  136. }
  137. else
  138. {
  139. var doReplace = replace(most, value);
  140. if (doReplace) most = value;
  141. }
  142. }
  143. return most;
  144. }
  145. // 无法输出正确结果。
  146. // public static T GetMin<T>(params IComparable[] values)
  147. // {
  148. // var result = GetMost((a, b) => a.CompareTo(b) == 1, values);
  149. // return result == null ? default : (T)result;
  150. // }
  151. // 无法输出正确结果。
  152. // public static T GetMin<T>(params IComparable<T>[] values)
  153. // {
  154. // var result = GetMost((a, b) => a.CompareTo((T)b) == 1, values);
  155. // return result == null ? default : (T)result;
  156. // }
  157. // 无法输出正确结果。
  158. // public static T GetMax<T>(params IComparable[] values)
  159. // {
  160. // var result = GetMost((a, b) => a.CompareTo(b) == -1, values);
  161. // return result == null ? default : (T)result;
  162. // }
  163. // 无法输出正确结果。
  164. // public static T GetMax<T>(params IComparable<T>[] values)
  165. // {
  166. // var result = GetMost((a, b) => a.CompareTo((T)b) == -1, values);
  167. // return result == null ? default : (T)result;
  168. // }
  169. /// <summary>最小值。</summary>
  170. public static byte Min(params byte[] values) => GetMost((a, b) => a > b, values);
  171. /// <summary>最小值。</summary>
  172. public static int Min(params int[] values) => GetMost((a, b) => a > b, values);
  173. /// <summary>最小值。</summary>
  174. public static long Min(params long[] values) => GetMost((a, b) => a > b, values);
  175. /// <summary>最小值。</summary>
  176. public static float Min(params float[] values) => GetMost((a, b) => a > b, values);
  177. /// <summary>最小值。</summary>
  178. public static double Min(params double[] values) => GetMost((a, b) => a > b, values);
  179. /// <summary>最小值。</summary>
  180. public static decimal Min(params decimal[] values) => GetMost((a, b) => a > b, values);
  181. /// <summary>最大值。</summary>
  182. public static byte Max(params byte[] values) => GetMost((a, b) => a < b, values);
  183. /// <summary>最大值。</summary>
  184. public static int Max(params int[] values) => GetMost((a, b) => a < b, values);
  185. /// <summary>最大值。</summary>
  186. public static long Max(params long[] values) => GetMost((a, b) => a < b, values);
  187. /// <summary>最大值。</summary>
  188. public static float Max(params float[] values) => GetMost((a, b) => a < b, values);
  189. /// <summary>最大值。</summary>
  190. public static double Max(params double[] values) => GetMost((a, b) => a < b, values);
  191. /// <summary>最大值。</summary>
  192. public static decimal Max(params decimal[] values) => GetMost((a, b) => a < b, values);
  193. #endregion
  194. /// <summary>Pearson Correlation Coefficient 皮尔逊相关系数。计算两个数组的相似度。数组长度不相等时,以 0 填充不足的长度。</summary>
  195. /// <remarks>
  196. /// <para>0.8 ~ 1.0 : 极强相关</para>
  197. /// <para>0.6 ~ 0.8 : 强相关</para>
  198. /// <para>0.4 ~ 0.6 : 中等程度相关</para>
  199. /// <para>0.2 ~ 0.4 : 弱相关</para>
  200. /// <para>0.0 ~ 0.2 : 极弱相关或无相关</para>
  201. /// </remarks>
  202. /// <exception cref="ArgumentException"></exception>
  203. public static double Pearson(double[] bytes1, double[] bytes2)
  204. {
  205. var length1 = bytes1 == null ? 0L : bytes1.LongLength;
  206. var length2 = bytes2 == null ? 0L : bytes2.LongLength;
  207. var length = Math.Max(length1, length2);
  208. if (length < 1) return 1D;
  209. var x = new double[length];
  210. var y = new double[length];
  211. for (var i = 0L; i < length; i++)
  212. {
  213. if (i < length1) x[i] = bytes1[i];
  214. if (i < length2) y[i] = bytes2[i];
  215. }
  216. int n = x.Length; // 数组长度。
  217. double s = 0d; // 分子。
  218. double m1 = 0d, m2 = 0d; // 分母。
  219. double xa = Average(x);
  220. double ya = Average(y);
  221. for (int i = 0; i < n; i++)
  222. {
  223. s += (x[i] - xa) * (y[i] - ya);
  224. m1 += Math.Pow(x[i] - xa, 2);
  225. m2 += Math.Pow(y[i] - ya, 2);
  226. }
  227. double r = s / (Math.Sqrt(m1) * Math.Sqrt(m2));
  228. return r;
  229. }
  230. }
  231. }