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.

1084 lines
44 KiB

4 years ago
2 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
3 years ago
4 years ago
4 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
2 years ago
4 years ago
  1. using Apewer.Internals;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Runtime.InteropServices;
  6. using System.Text;
  7. using System.Text.RegularExpressions;
  8. namespace Apewer
  9. {
  10. /// <summary>数值实用工具。</summary>
  11. public static class NumberUtility
  12. {
  13. #region 随机数。
  14. /// <summary>用于生成随机数的时钟位置。</summary>
  15. private static int RandomSeed = Guid.NewGuid().ToString().GetHashCode();
  16. private static void RandomInit()
  17. {
  18. var now = DateTime.Now;
  19. var timer = (float)((double)(checked((60 * now.Hour + now.Minute) * 60 + now.Second)) + (double)now.Millisecond / 1000.0);
  20. int num1 = RandomSeed;
  21. int num2 = BitConverter.ToInt32(BitConverter.GetBytes(timer), 0);
  22. num2 = ((num2 & 65535) ^ num2 >> 16) << 8;
  23. num1 = (num1 & -16776961) | num2;
  24. RandomSeed = num1;
  25. }
  26. /// <summary>生成不大于 1 的随机数,最小为 0。</summary>
  27. public static float Random(float max = 1F)
  28. {
  29. RandomInit();
  30. int num1 = RandomSeed;
  31. if ((double)max != 0.0)
  32. {
  33. if ((double)max < 0.0)
  34. {
  35. num1 = BitConverter.ToInt32(BitConverter.GetBytes(max), 0);
  36. long vnum2 = (long)num1;
  37. vnum2 &= unchecked((long)((ulong)-1));
  38. num1 = checked((int)(vnum2 + (vnum2 >> 24) & 16777215L));
  39. }
  40. num1 = checked((int)(unchecked((long)num1) * 1140671485L + 12820163L & 16777215L));
  41. }
  42. RandomSeed = num1;
  43. return (float)num1 / 16777216f;
  44. }
  45. /// <summary>生成随机整数,包含最小值和最大值。</summary>
  46. /// <param name="min">最小值。</param>
  47. /// <param name="max">最大值。</param>
  48. /// <returns></returns>
  49. public static int Random(int max, int min = 0)
  50. {
  51. if (max == min) return max;
  52. if (max < min)
  53. {
  54. var temp = max;
  55. max = min;
  56. min = temp;
  57. }
  58. var rate = (max - min + 1) * Random();
  59. var result = min + (int)rate;
  60. return result;
  61. }
  62. /// <summary>对数组填充随机数。<br />0 &lt;= value &lt; 1.0</summary>
  63. public static void Random(float[] array, int offset = 0, int count = -1)
  64. {
  65. if (array == null) return;
  66. if (count == 0) return;
  67. var length = array.LongLength;
  68. var end = length;
  69. if (count > 0) end = offset + count;
  70. if (end > length) end = length;
  71. RandomInit();
  72. var max = 1.0;
  73. for (var i = offset; i < end; i++)
  74. {
  75. if (i < 0) continue;
  76. int num1 = RandomSeed;
  77. if ((double)max != 0.0)
  78. {
  79. if ((double)max < 0.0)
  80. {
  81. num1 = BitConverter.ToInt32(BitConverter.GetBytes(max), 0);
  82. long vnum2 = (long)num1;
  83. vnum2 &= unchecked((long)((ulong)-1));
  84. num1 = checked((int)(vnum2 + (vnum2 >> 24) & 16777215L));
  85. }
  86. num1 = checked((int)(unchecked((long)num1) * 1140671485L + 12820163L & 16777215L));
  87. }
  88. RandomSeed = num1;
  89. array[i] = (float)num1 / 16777216f;
  90. }
  91. }
  92. /// <summary>对数组填充随机数。<br />0 &lt;= value &lt;= 255</summary>
  93. public static void Random(byte[] array, int offset = 0, int count = -1) { }
  94. static ulong UuidGetSystemTime(DateTime dt)
  95. {
  96. /* UUID system time starts at October 15, 1582 */
  97. // const long TICKS_PER_CLOCK_TICK = 1000L;
  98. const long SECSPERDAY = 86400L;
  99. const long TICKSPERSEC = 10000000L;
  100. const long SECS_15_OCT_1582_TO_1601 = (17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY;
  101. const long TICKS_15_OCT_1582_TO_1601 = SECS_15_OCT_1582_TO_1601 * TICKSPERSEC;
  102. var ticks = dt.Ticks;
  103. ticks += (17 + 30 + 31 + 365 * 18 + 5) * SECSPERDAY;
  104. ticks += TICKS_15_OCT_1582_TO_1601;
  105. return default;
  106. }
  107. /// <summary>生成 GUID。</summary>
  108. static byte[] NewGuid()
  109. {
  110. // DWORD Data1 // 随机数
  111. // WORD Data2 // 和时间相关
  112. // WORD Data3 // 和时间相关
  113. // BYTE Data4[8] // 和网卡 MAC 相关
  114. var guid = new byte[16];
  115. // 全部生成随机数。
  116. for (var i = 0; i < 16; i++) guid[i] = Convert.ToByte(NumberUtility.Random(255, 0));
  117. guid[6] &= 0x0f;
  118. guid[6] |= 0x04;
  119. guid[7] &= 0xff;
  120. guid[7] |= 0x00;
  121. guid[8] &= 0x3f;
  122. guid[8] |= 0x80;
  123. return guid;
  124. }
  125. #endregion
  126. #region 线程锁
  127. static Int32Locker _int32_locker = new Int32Locker();
  128. static Int64Locker _int64_locker = new Int64Locker();
  129. /// <summary>锁定数值,在锁中执行函数。</summary>
  130. /// <param name="value">要锁定的文本。</param>
  131. /// <param name="inLock">要在锁中执行的函数。</param>
  132. /// <exception cref="ArgumentNullException"></exception>
  133. public static T Lock<T>(this int value, Func<T> inLock)
  134. {
  135. if (inLock == null) throw new ArgumentNullException(nameof(inLock));
  136. return _int32_locker.InLock(value, inLock);
  137. }
  138. /// <summary>锁定文本,在锁中执行函数。</summary>
  139. /// <param name="value">要锁定的文本。</param>
  140. /// <param name="inLock">要在锁中执行的函数。</param>
  141. /// <exception cref="ArgumentNullException"></exception>
  142. public static void Lock(this int value, Action inLock)
  143. {
  144. if (inLock == null) throw new ArgumentNullException(nameof(inLock));
  145. _int32_locker.InLock(value, inLock);
  146. }
  147. /// <summary>锁定数值,在锁中执行函数。</summary>
  148. /// <param name="value">要锁定的文本。</param>
  149. /// <param name="inLock">要在锁中执行的函数。</param>
  150. /// <exception cref="ArgumentNullException"></exception>
  151. public static T Lock<T>(this long value, Func<T> inLock)
  152. {
  153. if (inLock == null) throw new ArgumentNullException(nameof(inLock));
  154. return _int64_locker.InLock(value, inLock);
  155. }
  156. /// <summary>锁定文本,在锁中执行函数。</summary>
  157. /// <param name="value">要锁定的文本。</param>
  158. /// <param name="inLock">要在锁中执行的函数。</param>
  159. /// <exception cref="ArgumentNullException"></exception>
  160. public static void Lock(this long value, Action inLock)
  161. {
  162. if (inLock == null) throw new ArgumentNullException(nameof(inLock));
  163. _int64_locker.InLock(value, inLock);
  164. }
  165. #endregion
  166. #region Restrict 约束值范围。
  167. /// <summary>约束值范围,若源值不在范围中,则修改为接近的值。</summary>
  168. public static T Restrict<T>(T origin, T min, T max) where T : IComparable
  169. {
  170. try
  171. {
  172. // 检查条件 min > max : 返回原始值。
  173. var condition = min.CompareTo(max);
  174. if (condition > 0) return origin;
  175. if (origin.CompareTo(min) < 0) return min;
  176. if (origin.CompareTo(max) > 0) return max;
  177. return origin;
  178. }
  179. catch { }
  180. return origin;
  181. }
  182. #endregion
  183. #region 表达式计算
  184. /// <summary>计算文本表达式,以 Int64 输出结果。</summary>
  185. public static long ComputeInt64(this string expression)
  186. {
  187. var result = Source.SourceUtility.Compute(expression);
  188. if (result == null) return 0L;
  189. if (result is long @long) return @long;
  190. return Int64(result);
  191. }
  192. /// <summary>计算文本表达式,以 Double 输出结果。</summary>
  193. public static double ComputeDouble(this string expression)
  194. {
  195. var result = Source.SourceUtility.Compute(expression);
  196. if (result == null) return 0D;
  197. if (result is double @double) return @double;
  198. return Double(result);
  199. }
  200. #endregion
  201. #region 求和
  202. /// <summary>求和。</summary>
  203. public static int Sum(params byte[] values)
  204. {
  205. if (values == null) return 0;
  206. var result = 0;
  207. foreach (var i in values) result += i;
  208. return result;
  209. }
  210. /// <summary>求和。</summary>
  211. public static int Sum(params short[] values)
  212. {
  213. if (values == null) return 0;
  214. var result = 0;
  215. foreach (var i in values) result += i;
  216. return result;
  217. }
  218. /// <summary>求和。</summary>
  219. public static int Sum(params int[] values)
  220. {
  221. if (values == null) return 0;
  222. var result = 0;
  223. foreach (var i in values) result += i;
  224. return result;
  225. }
  226. /// <summary>求和。</summary>
  227. public static long Sum(params long[] values)
  228. {
  229. if (values == null) return 0;
  230. var result = 0L;
  231. foreach (var i in values) result += i;
  232. return result;
  233. }
  234. /// <summary>求和。</summary>
  235. public static int Sum(params sbyte[] values)
  236. {
  237. if (values == null) return 0;
  238. var result = 0;
  239. foreach (var i in values) result += i;
  240. return result;
  241. }
  242. /// <summary>求和。</summary>
  243. public static int Sum(params ushort[] values)
  244. {
  245. if (values == null) return 0;
  246. var result = 0;
  247. foreach (var i in values) result += i;
  248. return result;
  249. }
  250. /// <summary>求和。</summary>
  251. public static uint Sum(params uint[] values)
  252. {
  253. if (values == null) return 0;
  254. var result = 0U;
  255. foreach (var i in values) result += i;
  256. return result;
  257. }
  258. /// <summary>求和。</summary>
  259. public static ulong Sum(params ulong[] values)
  260. {
  261. if (values == null) return 0;
  262. var result = 0UL;
  263. foreach (var i in values) result += i;
  264. return result;
  265. }
  266. /// <summary>求和。</summary>
  267. public static float Sum(params float[] values)
  268. {
  269. if (values == null) return 0;
  270. var result = 0F;
  271. foreach (var i in values) result += i;
  272. return result;
  273. }
  274. /// <summary>求和。</summary>
  275. public static double Sum(params double[] values)
  276. {
  277. if (values == null) return 0;
  278. var result = 0D;
  279. foreach (var i in values) result += i;
  280. return result;
  281. }
  282. /// <summary>求和。</summary>
  283. public static decimal Sum(params decimal[] values)
  284. {
  285. if (values == null) return 0;
  286. var result = 0M;
  287. foreach (var i in values) result += i;
  288. return result;
  289. }
  290. #endregion
  291. #region 平均值
  292. /// <summary>平均值。</summary>
  293. public static double Average(params byte[] values) => values.IsEmpty() ? 0 : (Sum(values) / Convert.ToDouble(values.Length));
  294. /// <summary>平均值。</summary>
  295. public static double Average(params short[] values) => values.IsEmpty() ? 0 : (Sum(values) / Convert.ToDouble(values.Length));
  296. /// <summary>平均值。</summary>
  297. public static double Average(params int[] values) => values.IsEmpty() ? 0 : (Sum(values) / Convert.ToDouble(values.Length));
  298. /// <summary>平均值。</summary>
  299. public static double Average(params long[] values) => values.IsEmpty() ? 0 : (Sum(values) / Convert.ToDouble(values.Length));
  300. /// <summary>平均值。</summary>
  301. public static double Average(params sbyte[] values) => values.IsEmpty() ? 0 : (Sum(values) / Convert.ToDouble(values.Length));
  302. /// <summary>平均值。</summary>
  303. public static double Average(params ushort[] values) => values.IsEmpty() ? 0 : (Sum(values) / Convert.ToDouble(values.Length));
  304. /// <summary>平均值。</summary>
  305. public static double Average(params uint[] values) => values.IsEmpty() ? 0 : (Sum(values) / Convert.ToDouble(values.Length));
  306. /// <summary>平均值。</summary>
  307. public static double Average(params ulong[] values) => values.IsEmpty() ? 0 : (Sum(values) / Convert.ToDouble(values.Length));
  308. /// <summary>平均值。</summary>
  309. public static float Average(params float[] values) => values.IsEmpty() ? 0 : (Sum(values) / values.Length);
  310. /// <summary>平均值。</summary>
  311. public static double Average(params double[] values) => values.IsEmpty() ? 0 : (Sum(values) / values.Length);
  312. /// <summary>平均值。</summary>
  313. public static decimal Average(params decimal[] values) => values.IsEmpty() ? 0 : (Sum(values) / values.Length);
  314. #endregion
  315. #region 标准差
  316. /// <summary>计算标准差。</summary>
  317. /// <param name="values">值。</param>
  318. /// <param name="sample">计算样本标准差,分母为 n - 1。此值为 false 时计算总体标准差。</param>
  319. public static double Stdev(this IEnumerable<double> values, bool sample = false)
  320. {
  321. if (values == null) return 0;
  322. var count = 0;
  323. var sum = 0D;
  324. var up = 0D;
  325. if (values is double[] array)
  326. {
  327. count = array.Length;
  328. if (count < 1) return 0;
  329. for (var i = 0; i < count; i++) sum += array[i];
  330. var avg = sum / count;
  331. for (var i = 0; i < count; i++) up += (array[i] - avg) * (array[i] - avg);
  332. }
  333. else if (values is IList<double> list)
  334. {
  335. count = list.Count;
  336. if (count < 1) return 0;
  337. for (var i = 0; i < count; i++) sum += list[i];
  338. var avg = sum / count;
  339. for (var i = 0; i < count; i++) up += (list[i] - avg) * (list[i] - avg);
  340. }
  341. else
  342. {
  343. foreach (var value in values)
  344. {
  345. sum += value;
  346. count++;
  347. }
  348. if (count < 1) return 0;
  349. var avg = sum / count;
  350. foreach (var value in values)
  351. {
  352. up += (value - avg) * (value - avg);
  353. count++;
  354. }
  355. }
  356. // 样本标准差,最少要 2 个值。
  357. if (sample)
  358. {
  359. var down = count - 1;
  360. if (down == 0) return 0;
  361. var sigma = Math.Sqrt(up / down);
  362. return sigma;
  363. }
  364. else
  365. {
  366. var sigma = Math.Sqrt(up / count);
  367. return sigma;
  368. }
  369. }
  370. /// <summary>计算总体标准差,分母为 n。</summary>
  371. /// <param name="values">值。</param>
  372. public static double StdevP(this IEnumerable<double> values) => Stdev(values, false);
  373. /// <summary>计算样本标准差,分母为 n - 1。</summary>
  374. /// <param name="values">值。</param>
  375. public static double StdevS(this IEnumerable<double> values) => Stdev(values, true);
  376. /// <summary>计算标准差。</summary>
  377. /// <param name="values">值。</param>
  378. /// <param name="sample">计算样本标准差,分母为 n - 1。此值为 false 时计算总体标准差。</param>
  379. public static float Stdev(this IEnumerable<float> values, bool sample = false)
  380. {
  381. if (values == null) return 0;
  382. var count = 0;
  383. var sum = 0F;
  384. var up = 0F;
  385. if (values is float[] array)
  386. {
  387. count = array.Length;
  388. if (count < 1) return 0;
  389. for (var i = 0; i < count; i++) sum += array[i];
  390. var avg = sum / count;
  391. for (var i = 0; i < count; i++) up += (array[i] - avg) * (array[i] - avg);
  392. }
  393. else if (values is IList<float> list)
  394. {
  395. count = list.Count;
  396. if (count < 1) return 0;
  397. for (var i = 0; i < count; i++) sum += list[i];
  398. var avg = sum / count;
  399. for (var i = 0; i < count; i++) up += (list[i] - avg) * (list[i] - avg);
  400. }
  401. else
  402. {
  403. foreach (var value in values)
  404. {
  405. sum += value;
  406. count++;
  407. }
  408. if (count < 1) return 0;
  409. var avg = sum / count;
  410. foreach (var value in values)
  411. {
  412. up += (value - avg) * (value - avg);
  413. count++;
  414. }
  415. }
  416. // 样本标准差,最少要 2 个值。
  417. if (sample)
  418. {
  419. var down = count - 1;
  420. if (down == 0) return 0;
  421. var sigma = Convert.ToSingle(Math.Sqrt(up / down));
  422. return sigma;
  423. }
  424. else
  425. {
  426. var sigma = Convert.ToSingle(Math.Sqrt(up / count));
  427. return sigma;
  428. }
  429. }
  430. /// <summary>计算总体标准差,分母为 n。</summary>
  431. /// <param name="values">值。</param>
  432. public static float StdevP(this IEnumerable<float> values) => Stdev(values, false);
  433. /// <summary>计算样本标准差,分母为 n - 1。</summary>
  434. /// <param name="values">值。</param>
  435. public static float StdevS(this IEnumerable<float> values) => Stdev(values, true);
  436. /// <summary>计算标准差。</summary>
  437. /// <param name="values">值。</param>
  438. /// <param name="sample">计算样本标准差,分母为 n - 1。此值为 false 时计算总体标准差。</param>
  439. public static decimal Stdev(this IEnumerable<decimal> values, bool sample = false)
  440. {
  441. if (values == null) return 0;
  442. var count = 0;
  443. var sum = 0M;
  444. var up = 0M;
  445. if (values is decimal[] array)
  446. {
  447. count = array.Length;
  448. if (count < 1) return 0;
  449. for (var i = 0; i < count; i++) sum += array[i];
  450. var avg = sum / count;
  451. for (var i = 0; i < count; i++) up += (array[i] - avg) * (array[i] - avg);
  452. }
  453. else if (values is IList<decimal> list)
  454. {
  455. count = list.Count;
  456. if (count < 1) return 0;
  457. for (var i = 0; i < count; i++) sum += list[i];
  458. var avg = sum / count;
  459. for (var i = 0; i < count; i++) up += (list[i] - avg) * (list[i] - avg);
  460. }
  461. else
  462. {
  463. foreach (var value in values)
  464. {
  465. sum += value;
  466. count++;
  467. }
  468. if (count < 1) return 0;
  469. var avg = sum / count;
  470. foreach (var value in values)
  471. {
  472. up += (value - avg) * (value - avg);
  473. count++;
  474. }
  475. }
  476. // 样本标准差,最少要 2 个值。
  477. if (sample)
  478. {
  479. var down = count - 1;
  480. if (down == 0) return 0;
  481. var sigma = Convert.ToDecimal(Math.Sqrt(Convert.ToDouble(up / down)));
  482. return sigma;
  483. }
  484. else
  485. {
  486. var sigma = Convert.ToDecimal(Math.Sqrt(Convert.ToDouble(up / count)));
  487. return sigma;
  488. }
  489. }
  490. /// <summary>计算总体标准差,分母为 n。</summary>
  491. /// <param name="values">值。</param>
  492. public static decimal StdevP(this IEnumerable<decimal> values) => Stdev(values, false);
  493. /// <summary>计算样本标准差,分母为 n - 1。</summary>
  494. /// <param name="values">值。</param>
  495. public static decimal StdevS(this IEnumerable<decimal> values) => Stdev(values, true);
  496. #endregion
  497. #region 最小值
  498. private static T Most<T>(Func<T, T, bool> replace, T[] values)
  499. {
  500. if (values == null) return default;
  501. var length = values.LongLength;
  502. if (length == 0L) return default;
  503. if (length == 1L) return values[0L];
  504. var most = values[0];
  505. for (var i = 1L; i < length; i++)
  506. {
  507. var value = values[i];
  508. if (value == null) continue;
  509. if (most == null)
  510. {
  511. most = value;
  512. }
  513. else
  514. {
  515. var doReplace = replace(most, value);
  516. if (doReplace) most = value;
  517. }
  518. }
  519. return most;
  520. }
  521. /// <summary>最小值。</summary>
  522. public static byte Min(params byte[] values) => Most((a, b) => a > b, values);
  523. /// <summary>最小值。</summary>
  524. public static short Min(params short[] values) => Most((a, b) => a > b, values);
  525. /// <summary>最小值。</summary>
  526. public static int Min(params int[] values) => Most((a, b) => a > b, values);
  527. /// <summary>最小值。</summary>
  528. public static long Min(params long[] values) => Most((a, b) => a > b, values);
  529. /// <summary>最小值。</summary>
  530. public static sbyte Min(params sbyte[] values) => Most((a, b) => a > b, values);
  531. /// <summary>最小值。</summary>
  532. public static ushort Min(params ushort[] values) => Most((a, b) => a > b, values);
  533. /// <summary>最小值。</summary>
  534. public static uint Min(params uint[] values) => Most((a, b) => a > b, values);
  535. /// <summary>最小值。</summary>
  536. public static ulong Min(params ulong[] values) => Most((a, b) => a > b, values);
  537. /// <summary>最小值。</summary>
  538. public static float Min(params float[] values) => Most((a, b) => a > b, values);
  539. /// <summary>最小值。</summary>
  540. public static double Min(params double[] values) => Most((a, b) => a > b, values);
  541. /// <summary>最小值。</summary>
  542. public static decimal Min(params decimal[] values) => Most((a, b) => a > b, values);
  543. #endregion
  544. #region 最大值
  545. /// <summary>最大值。</summary>
  546. public static byte Max(params byte[] values) => Most((a, b) => a < b, values);
  547. /// <summary>最大值。</summary>
  548. public static short Max(params short[] values) => Most((a, b) => a < b, values);
  549. /// <summary>最大值。</summary>
  550. public static int Max(params int[] values) => Most((a, b) => a < b, values);
  551. /// <summary>最大值。</summary>
  552. public static long Max(params long[] values) => Most((a, b) => a < b, values);
  553. /// <summary>最大值。</summary>
  554. public static sbyte Max(params sbyte[] values) => Most((a, b) => a < b, values);
  555. /// <summary>最大值。</summary>
  556. public static ushort Max(params ushort[] values) => Most((a, b) => a < b, values);
  557. /// <summary>最大值。</summary>
  558. public static uint Max(params uint[] values) => Most((a, b) => a < b, values);
  559. /// <summary>最大值。</summary>
  560. public static ulong Max(params ulong[] values) => Most((a, b) => a < b, values);
  561. /// <summary>最大值。</summary>
  562. public static float Max(params float[] values) => Most((a, b) => a < b, values);
  563. /// <summary>最大值。</summary>
  564. public static double Max(params double[] values) => Most((a, b) => a < b, values);
  565. /// <summary>最大值。</summary>
  566. public static decimal Max(params decimal[] values) => Most((a, b) => a < b, values);
  567. #endregion
  568. #region 极差
  569. /// <summary>极差。</summary>
  570. public static int Range(params int[] values) => Max(values) - Min(values);
  571. /// <summary>极差。</summary>
  572. public static long Range(params long[] values) => Max(values) - Min(values);
  573. /// <summary>极差。</summary>
  574. public static float Range(params float[] values) => Max(values) - Min(values);
  575. /// <summary>极差。</summary>
  576. public static double Range(params double[] values) => Max(values) - Min(values);
  577. /// <summary>极差。</summary>
  578. public static decimal Range(params decimal[] values) => Max(values) - Min(values);
  579. #endregion
  580. #region 相关性
  581. /// <summary>Pearson Correlation Coefficient 皮尔逊相关系数。计算两个数组的相似度。数组长度不相等时,以 0 填充不足的长度。</summary>
  582. /// <remarks>0.8 ~ 1.0 : 极强相关<br />0.6 ~ 0.8 : 强相关<br />0.4 ~ 0.6 : 中等程度相关<br />0.2 ~ 0.4 : 弱相关<br />0.0 ~ 0.2 : 极弱相关或无相关</remarks>
  583. /// <exception cref="ArgumentException"></exception>
  584. public static double Pearson(double[] bytes1, double[] bytes2)
  585. {
  586. var length1 = bytes1 == null ? 0L : bytes1.LongLength;
  587. var length2 = bytes2 == null ? 0L : bytes2.LongLength;
  588. var length = Math.Max(length1, length2);
  589. if (length < 1) return 1D;
  590. var x = new double[length];
  591. var y = new double[length];
  592. for (var i = 0L; i < length; i++)
  593. {
  594. if (i < length1) x[i] = bytes1[i];
  595. if (i < length2) y[i] = bytes2[i];
  596. }
  597. int n = x.Length; // 数组长度。
  598. double s = 0d; // 分子。
  599. double m1 = 0d, m2 = 0d; // 分母。
  600. double xa = Average(x);
  601. double ya = Average(y);
  602. for (int i = 0; i < n; i++)
  603. {
  604. s += (x[i] - xa) * (y[i] - ya);
  605. m1 += Math.Pow(x[i] - xa, 2);
  606. m2 += Math.Pow(y[i] - ya, 2);
  607. }
  608. double r = s / (Math.Sqrt(m1) * Math.Sqrt(m2));
  609. return r;
  610. }
  611. #endregion
  612. #region 从 String 转为数值。
  613. // 修剪数值字符串。
  614. private static string Trim(string text)
  615. {
  616. if (string.IsNullOrEmpty(text)) return null;
  617. const string allowed = "0123456789.%+-Ee。";
  618. var input = text.Length;
  619. var output = 0;
  620. var chars = new char[input];
  621. for (var i = 0; i < text.Length; i++)
  622. {
  623. var c = text[i];
  624. if (c == '。') c = '.';
  625. else if (allowed.IndexOf(c) < 0) continue;
  626. chars[output] = c;
  627. output += 1;
  628. }
  629. if (output == input) return text;
  630. if (output < 1) return null;
  631. return new string(chars, 0, output);
  632. }
  633. private static T GetNumber<T>(object @object, Func<string, T> convert, Func<T, double, T> percent = null)
  634. {
  635. if (@object == null) return default(T);
  636. if (@object is T) return (T)@object;
  637. var text = (@object is string) ? (string)@object : @object.ToString();
  638. var trim = Trim(text);
  639. if (trim == null) return default;
  640. // 获取百分号的个数。
  641. var pow = 0;
  642. while (trim.Length > 0 && trim.EndsWith("%"))
  643. {
  644. trim = trim.Substring(0, trim.Length - 1);
  645. pow += 1;
  646. }
  647. if (trim.Length < 1) return default;
  648. // 转换。
  649. try
  650. {
  651. var value = convert(trim);
  652. if (pow > 0 && percent != null)
  653. {
  654. var denominator = Math.Pow(100, pow);
  655. value = percent(value, denominator);
  656. }
  657. return value;
  658. }
  659. catch { return default; }
  660. }
  661. private static decimal DecimalAsFloat(string text)
  662. {
  663. try { return Convert.ToDecimal(text); } catch { }
  664. try { return decimal.Parse(text, NumberStyles.Float); } catch { }
  665. return default(decimal);
  666. }
  667. /// <summary>获取布尔对象。</summary>
  668. public static bool Boolean(object any)
  669. {
  670. if (any.IsNull()) return false;
  671. if (any is bool _bool) return _bool;
  672. if (any is byte _byte) return _byte == 1;
  673. if (any is sbyte _sbyte) return _sbyte == 1;
  674. if (any is short _short) return _short == 1;
  675. if (any is ushort _ushort) return _ushort == 1;
  676. if (any is int _int) return _int == 1;
  677. if (any is uint _uint) return _uint == 1;
  678. if (any is long _long) return _long == 1;
  679. if (any is ulong _ulong) return _ulong == 1;
  680. if (any is float _float) return _float == 1;
  681. if (any is double _double) return _double == 1;
  682. if (any is decimal _decimal) return _decimal == 1;
  683. if (any is string _string)
  684. {
  685. var lower = TextUtility.Lower(_string);
  686. if (lower == "true" || lower == "yes" || lower == "y" || lower == "1") return true;
  687. }
  688. return false;
  689. }
  690. private static Tout Try<Tin, Tout>(Tin value, Func<Tin, Tout> func)
  691. {
  692. try { return func.Invoke(value); }
  693. catch { return default(Tout); }
  694. }
  695. /// <summary>获取单精度浮点对象。</summary>
  696. public static float Float(object number)
  697. {
  698. if (number is bool _bool) return Try(_bool, Convert.ToSingle);
  699. if (number is byte _byte) return Try(_byte, Convert.ToSingle);
  700. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToSingle);
  701. if (number is short _short) return Try(_short, Convert.ToSingle);
  702. if (number is ushort _ushort) return Try(_ushort, Convert.ToSingle);
  703. if (number is int _int) return Try(_int, Convert.ToSingle);
  704. if (number is uint _uint) return Try(_uint, Convert.ToSingle);
  705. if (number is long _long) return Try(_long, Convert.ToSingle);
  706. if (number is ulong _ulong) return Try(_ulong, Convert.ToSingle);
  707. if (number is float _float) return Try(_float, Convert.ToSingle);
  708. if (number is double _double) return Try(_double, Convert.ToSingle);
  709. if (number is decimal _decimal) return Try(_decimal, Convert.ToSingle);
  710. return GetNumber(number, Convert.ToSingle, (v, d) => v / Convert.ToSingle(d));
  711. }
  712. /// <summary>获取单精度浮点对象。</summary>
  713. public static float Single(object number)
  714. {
  715. if (number is bool _bool) return Try(_bool, Convert.ToSingle);
  716. if (number is byte _byte) return Try(_byte, Convert.ToSingle);
  717. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToSingle);
  718. if (number is short _short) return Try(_short, Convert.ToSingle);
  719. if (number is ushort _ushort) return Try(_ushort, Convert.ToSingle);
  720. if (number is int _int) return Try(_int, Convert.ToSingle);
  721. if (number is uint _uint) return Try(_uint, Convert.ToSingle);
  722. if (number is long _long) return Try(_long, Convert.ToSingle);
  723. if (number is ulong _ulong) return Try(_ulong, Convert.ToSingle);
  724. if (number is float _float) return Try(_float, Convert.ToSingle);
  725. if (number is double _double) return Try(_double, Convert.ToSingle);
  726. if (number is decimal _decimal) return Try(_decimal, Convert.ToSingle);
  727. return GetNumber(number, Convert.ToSingle, (v, d) => v / Convert.ToSingle(d));
  728. }
  729. /// <summary>获取双精度浮点对象。</summary>
  730. public static double Double(object number)
  731. {
  732. if (number is bool _bool) return Try(_bool, Convert.ToDouble);
  733. if (number is byte _byte) return Try(_byte, Convert.ToDouble);
  734. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToDouble);
  735. if (number is short _short) return Try(_short, Convert.ToDouble);
  736. if (number is ushort _ushort) return Try(_ushort, Convert.ToDouble);
  737. if (number is int _int) return Try(_int, Convert.ToDouble);
  738. if (number is uint _uint) return Try(_uint, Convert.ToDouble);
  739. if (number is long _long) return Try(_long, Convert.ToDouble);
  740. if (number is ulong _ulong) return Try(_ulong, Convert.ToDouble);
  741. if (number is float _float) return Try(_float, Convert.ToDouble);
  742. if (number is double _double) return Try(_double, Convert.ToDouble);
  743. if (number is decimal _decimal) return Try(_decimal, Convert.ToDouble);
  744. return GetNumber(number, Convert.ToDouble, (v, d) => v / d);
  745. }
  746. /// <summary>获取 Decimal 对象。</summary>
  747. public static decimal Decimal(object number)
  748. {
  749. if (number is bool _bool) return Try(_bool, Convert.ToDecimal);
  750. if (number is byte _byte) return Try(_byte, Convert.ToDecimal);
  751. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToDecimal);
  752. if (number is short _short) return Try(_short, Convert.ToDecimal);
  753. if (number is ushort _ushort) return Try(_ushort, Convert.ToDecimal);
  754. if (number is int _int) return Try(_int, Convert.ToDecimal);
  755. if (number is uint _uint) return Try(_uint, Convert.ToDecimal);
  756. if (number is long _long) return Try(_long, Convert.ToDecimal);
  757. if (number is ulong _ulong) return Try(_ulong, Convert.ToDecimal);
  758. if (number is float _float) return Try(_float, Convert.ToDecimal);
  759. if (number is double _double) return Try(_double, Convert.ToDecimal);
  760. if (number is decimal _decimal) return Try(_decimal, Convert.ToDecimal);
  761. return GetNumber(number, DecimalAsFloat, (v, d) => v / Convert.ToDecimal(d));
  762. }
  763. /// <summary>获取 Byte 对象。</summary>
  764. public static byte Byte(object number)
  765. {
  766. if (number is bool _bool) return Try(_bool, Convert.ToByte);
  767. if (number is byte _byte) return Try(_byte, Convert.ToByte);
  768. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToByte);
  769. if (number is short _short) return Try(_short, Convert.ToByte);
  770. if (number is ushort _ushort) return Try(_ushort, Convert.ToByte);
  771. if (number is int _int) return Try(_int, Convert.ToByte);
  772. if (number is uint _uint) return Try(_uint, Convert.ToByte);
  773. if (number is long _long) return Try(_long, Convert.ToByte);
  774. if (number is ulong _ulong) return Try(_ulong, Convert.ToByte);
  775. if (number is float _float) return Try(_float, Convert.ToByte);
  776. if (number is double _double) return Try(_double, Convert.ToByte);
  777. if (number is decimal _decimal) return Try(_decimal, Convert.ToByte);
  778. return GetNumber(number, Convert.ToByte);
  779. }
  780. /// <summary>获取 SByte 对象。</summary>
  781. public static sbyte SByte(object number)
  782. {
  783. if (number is bool _bool) return Try(_bool, Convert.ToSByte);
  784. if (number is byte _byte) return Try(_byte, Convert.ToSByte);
  785. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToSByte);
  786. if (number is short _short) return Try(_short, Convert.ToSByte);
  787. if (number is ushort _ushort) return Try(_ushort, Convert.ToSByte);
  788. if (number is int _int) return Try(_int, Convert.ToSByte);
  789. if (number is uint _uint) return Try(_uint, Convert.ToSByte);
  790. if (number is long _long) return Try(_long, Convert.ToSByte);
  791. if (number is ulong _ulong) return Try(_ulong, Convert.ToSByte);
  792. if (number is float _float) return Try(_float, Convert.ToSByte);
  793. if (number is double _double) return Try(_double, Convert.ToSByte);
  794. if (number is decimal _decimal) return Try(_decimal, Convert.ToSByte);
  795. return GetNumber(number, Convert.ToSByte);
  796. }
  797. /// <summary>获取 Int16 对象。</summary>
  798. public static short Int16(object number)
  799. {
  800. if (number is bool _bool) return Try(_bool, Convert.ToInt16);
  801. if (number is byte _byte) return Try(_byte, Convert.ToInt16);
  802. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToInt16);
  803. if (number is short _short) return Try(_short, Convert.ToInt16);
  804. if (number is ushort _ushort) return Try(_ushort, Convert.ToInt16);
  805. if (number is int _int) return Try(_int, Convert.ToInt16);
  806. if (number is uint _uint) return Try(_uint, Convert.ToInt16);
  807. if (number is long _long) return Try(_long, Convert.ToInt16);
  808. if (number is ulong _ulong) return Try(_ulong, Convert.ToInt16);
  809. if (number is float _float) return Try(_float, Convert.ToInt16);
  810. if (number is double _double) return Try(_double, Convert.ToInt16);
  811. if (number is decimal _decimal) return Try(_decimal, Convert.ToInt16);
  812. return GetNumber(number, Convert.ToInt16);
  813. }
  814. /// <summary>获取 UInt16 对象。</summary>
  815. public static ushort UInt16(object number)
  816. {
  817. if (number is bool _bool) return Try(_bool, Convert.ToUInt16);
  818. if (number is byte _byte) return Try(_byte, Convert.ToUInt16);
  819. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToUInt16);
  820. if (number is short _short) return Try(_short, Convert.ToUInt16);
  821. if (number is ushort _ushort) return Try(_ushort, Convert.ToUInt16);
  822. if (number is int _int) return Try(_int, Convert.ToUInt16);
  823. if (number is uint _uint) return Try(_uint, Convert.ToUInt16);
  824. if (number is long _long) return Try(_long, Convert.ToUInt16);
  825. if (number is ulong _ulong) return Try(_ulong, Convert.ToUInt16);
  826. if (number is float _float) return Try(_float, Convert.ToUInt16);
  827. if (number is double _double) return Try(_double, Convert.ToUInt16);
  828. if (number is decimal _decimal) return Try(_decimal, Convert.ToUInt16);
  829. return GetNumber(number, Convert.ToUInt16);
  830. }
  831. /// <summary>获取 Int32 对象。</summary>
  832. public static int Int32(object number)
  833. {
  834. if (number is bool _bool) return Try(_bool, Convert.ToInt32);
  835. if (number is byte _byte) return Try(_byte, Convert.ToInt32);
  836. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToInt32);
  837. if (number is short _short) return Try(_short, Convert.ToInt32);
  838. if (number is ushort _ushort) return Try(_ushort, Convert.ToInt32);
  839. if (number is int _int) return Try(_int, Convert.ToInt32);
  840. if (number is uint _uint) return Try(_uint, Convert.ToInt32);
  841. if (number is long _long) return Try(_long, Convert.ToInt32);
  842. if (number is ulong _ulong) return Try(_ulong, Convert.ToInt32);
  843. if (number is float _float) return Try(_float, Convert.ToInt32);
  844. if (number is double _double) return Try(_double, Convert.ToInt32);
  845. if (number is decimal _decimal) return Try(_decimal, Convert.ToInt32);
  846. return GetNumber(number, Convert.ToInt32);
  847. }
  848. /// <summary>获取 UInt32 对象。</summary>
  849. public static uint UInt32(object number)
  850. {
  851. if (number is bool _bool) return Try(_bool, Convert.ToUInt32);
  852. if (number is byte _byte) return Try(_byte, Convert.ToUInt32);
  853. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToUInt32);
  854. if (number is short _short) return Try(_short, Convert.ToUInt32);
  855. if (number is ushort _ushort) return Try(_ushort, Convert.ToUInt32);
  856. if (number is int _int) return Try(_int, Convert.ToUInt32);
  857. if (number is uint _uint) return Try(_uint, Convert.ToUInt32);
  858. if (number is long _long) return Try(_long, Convert.ToUInt32);
  859. if (number is ulong _ulong) return Try(_ulong, Convert.ToUInt32);
  860. if (number is float _float) return Try(_float, Convert.ToUInt32);
  861. if (number is double _double) return Try(_double, Convert.ToUInt32);
  862. if (number is decimal _decimal) return Try(_decimal, Convert.ToUInt32);
  863. return GetNumber(number, Convert.ToUInt32);
  864. }
  865. /// <summary>获取 Int64 对象。</summary>
  866. public static long Int64(object number)
  867. {
  868. if (number is bool _bool) return Try(_bool, Convert.ToInt64);
  869. if (number is byte _byte) return Try(_byte, Convert.ToInt64);
  870. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToInt64);
  871. if (number is short _short) return Try(_short, Convert.ToInt64);
  872. if (number is ushort _ushort) return Try(_ushort, Convert.ToInt64);
  873. if (number is int _int) return Try(_int, Convert.ToInt64);
  874. if (number is uint _uint) return Try(_uint, Convert.ToInt64);
  875. if (number is long _long) return Try(_long, Convert.ToInt64);
  876. if (number is ulong _ulong) return Try(_ulong, Convert.ToInt64);
  877. if (number is float _float) return Try(_float, Convert.ToInt64);
  878. if (number is double _double) return Try(_double, Convert.ToInt64);
  879. if (number is decimal _decimal) return Try(_decimal, Convert.ToInt64);
  880. return GetNumber(number, Convert.ToInt64);
  881. }
  882. /// <summary>获取 UInt64 对象。</summary>
  883. public static ulong UInt64(object number)
  884. {
  885. if (number is bool _bool) return Try(_bool, Convert.ToUInt64);
  886. if (number is byte _byte) return Try(_byte, Convert.ToUInt64);
  887. if (number is sbyte _sbyte) return Try(_sbyte, Convert.ToUInt64);
  888. if (number is short _short) return Try(_short, Convert.ToUInt64);
  889. if (number is ushort _ushort) return Try(_ushort, Convert.ToUInt64);
  890. if (number is int _int) return Try(_int, Convert.ToUInt64);
  891. if (number is uint _uint) return Try(_uint, Convert.ToUInt64);
  892. if (number is long _long) return Try(_long, Convert.ToUInt64);
  893. if (number is ulong _ulong) return Try(_ulong, Convert.ToUInt64);
  894. if (number is float _float) return Try(_float, Convert.ToUInt64);
  895. if (number is double _double) return Try(_double, Convert.ToUInt64);
  896. if (number is decimal _decimal) return Try(_decimal, Convert.ToUInt64);
  897. return GetNumber(number, Convert.ToUInt64);
  898. }
  899. #endregion
  900. #region 转为字符串
  901. /// <summary>转为大写中文金额。</summary>
  902. public static string ToChinesePrice(decimal value)
  903. {
  904. if (value == 0M) return "零圆整";
  905. var s = value.ToString("#L#E#D#C#K#E#D#C#J#E#D#C#I#E#D#C#H#E#D#C#G#E#D#C#F#E#D#C#.0B0A");
  906. var d = Regex.Replace(s, @"((?<=-|^)[^1-9]*)|((?'z'0)[0A-E]*((?=[1-9])|(?'-z'(?=[F-L\.]|$))))|((?'b'[F-L])(?'z'0)[0A-L]*((?=[1-9])|(?'-z'(?=[\.]|$))))", "${b}${z}");
  907. var r = Regex.Replace(d, ".", m => "负元空零壹贰叁肆伍陆柒捌玖空空空空空空空分角拾佰仟万亿兆京垓秭穰"[m.Value[0] - '-'].ToString());
  908. if (!(r.Contains("分") || r.Contains("角"))) r = r + "整";
  909. if (value < 0M) r = "负" + r;
  910. return r;
  911. }
  912. #endregion
  913. }
  914. }