MathUtil.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using ET;
  5. namespace Hutool
  6. {
  7. public static class MathUtil
  8. {
  9. /// <summary>
  10. /// 检查指定位置的位是否为1
  11. /// </summary>
  12. /// <param name="value">要检查的整数</param>
  13. /// <param name="index">要检查的位位置</param>
  14. /// <returns>如果指定位置的位为1,则返回true;否则返回false,注意:index不合法将会返回false</returns>
  15. public static bool isBitSet(long value, int index)
  16. {
  17. // 检查指定的位位置是否在合法范围内
  18. //sizeof(int) * 8 的结果就是 long 类型的二进制位数.long占用8字节,即64位
  19. if (index < 0 || index >= sizeof(long) * 8)
  20. {
  21. Log.Error($"value:{value},index:{index},超出索引");
  22. return false;
  23. }
  24. // 使用按位与运算符 & 将指定位置的位与1进行比较
  25. // 如果结果不为0,则表示该位为1,返回true
  26. // 如果结果为0,则表示该位为0,返回false
  27. return (value & (1 << index)) != 0;
  28. }
  29. /// <summary>
  30. /// 将指定位置的位设置为1
  31. /// </summary>
  32. /// <param name="num">待修改的整数</param>
  33. /// <param name="bitPositions">要设置为1的位位置数组</param>
  34. /// <returns>修改后的整数,报错返回默认值,注:bitPositions不合法将返回原始num</returns>
  35. public static int SetBitsTo1(int num, int[] bitPositions)
  36. {
  37. // 检查位位置数组是否为空
  38. if (bitPositions == null)
  39. {
  40. Log.Error($"num:{num}, bitPositions is null.");
  41. return num;
  42. }
  43. // 检查位位置是否在合法范围内
  44. int bitCount = sizeof(int) * 8;
  45. foreach (int bitPos in bitPositions)
  46. {
  47. if (bitPos < 0 || bitPos >= bitCount)
  48. {
  49. Log.Error($"num:{num}, bitPositions bitPos:{bitPos} 超出索引");
  50. return num;
  51. }
  52. }
  53. var mask = bitPositions.Aggregate(0, (current, bitPos) => current | 1 << bitPos);
  54. return num | mask;
  55. }
  56. /// <summary>
  57. /// 32位中设置某一位为1
  58. /// </summary>
  59. /// <param name="num">待设置的32位整数</param>
  60. /// <param name="bitPos">要设置为1的位的位置</param>
  61. /// <returns>设置后的整数,注:bitPos不合法将返回原始num</returns>
  62. public static int SetBitsTo1(int num, int bitPos)
  63. {
  64. // 检查位位置是否在合法范围内
  65. if (bitPos < 0 || bitPos >= sizeof(int) * 8)
  66. {
  67. Log.Error($"num:{num}, bitPos:{bitPos} 超出索引.");
  68. return num;
  69. }
  70. // 使用按位或操作符 | 将指定位位置的位设置为1
  71. return num | (1 << bitPos);
  72. }
  73. /// <summary>
  74. /// 64位中,设置某一位为1
  75. /// </summary>
  76. /// <param name="num">待设置的64位整数</param>
  77. /// <param name="bitPos">要设置为1的位的位置</param>
  78. /// <returns>设置后的值,注:bitPos不合法将返回原始num</returns>
  79. public static long SetBitsTo1Long(long num, int bitPos)
  80. {
  81. // 检查位位置是否在合法范围内
  82. if (bitPos < 0 || bitPos >= sizeof(long) * 8)
  83. {
  84. Log.Error($"num:{num}, bitPos:{bitPos} 超出索引");
  85. return num;
  86. }
  87. return num | (1L << bitPos);
  88. }
  89. /// <summary>
  90. /// 将指定位置的位设置为0
  91. /// </summary>
  92. /// <param name="num">待修改的整数</param>
  93. /// <param name="bitPosition">要设置为0的位位置</param>
  94. /// <returns>修改后的整数,注:如果bitPosition不合法将返回原始num</returns>
  95. public static int SetBitsTo0(int num, int bitPosition)
  96. {
  97. // 检查位位置是否在合法范围内
  98. int bitCount = sizeof(int) * 8;
  99. if (bitPosition < 0 || bitPosition >= bitCount)
  100. {
  101. Log.Error($"num:{num}, bitPosition: {bitPosition} 超出索引");
  102. return num;
  103. }
  104. // 创建掩码
  105. int mask = 1 << bitPosition;
  106. // 使用掩码将指定位设置为0
  107. return num & ~mask;
  108. }
  109. /// <summary>
  110. /// 将指定位置的位设置为0
  111. /// </summary>
  112. /// <param name="num">待修改的整数</param>
  113. /// <param name="bitPositions">要设置为0的位位置数组</param>
  114. /// <returns>修改后的整数,注:bitPositions存在不合法的位将返回原始num</returns>
  115. public static int SetBitsTo0(int num, int[] bitPositions)
  116. {
  117. // 检查位位置数组是否为空
  118. if (bitPositions == null)
  119. {
  120. Log.Error("bitPositions is null.");
  121. return num;
  122. }
  123. // 检查位位置是否在合法范围内
  124. int bitCount = sizeof(int) * 8;
  125. foreach (int bitPos in bitPositions)
  126. {
  127. if (bitPos < 0 || bitPos >= bitCount)
  128. {
  129. Log.Error($"num:{num}, bitPositions bitPos:{bitPos} 超出索引");
  130. return num;
  131. }
  132. }
  133. var mask = bitPositions.Aggregate(0, (current, bitPos) => current | 1 << bitPos);
  134. return num & ~mask;
  135. }
  136. /// <summary>
  137. /// 统计32位无符号整数中的1位数目
  138. /// </summary>
  139. /// <param name="num">要统计的32位无符号整数</param>
  140. /// <returns>1的位数目</returns>
  141. public static int CountOnes(int num)
  142. {
  143. var count = 0;
  144. for (int i = 0; i < 32; i++)
  145. {
  146. // 检查 num 的最低位是否为1,如果是则 count 加1
  147. if ((num & 1) == 1)
  148. {
  149. count++;
  150. }
  151. // 将 num 向右移动一位,继续检查下一位
  152. num >>= 1;
  153. }
  154. return count;
  155. }
  156. /// <summary>
  157. /// 统计64位无符号整数中的1位数目
  158. /// </summary>
  159. /// <param name="num">要统计的64位无符号整数</param>
  160. /// <returns>1的位数目</returns>
  161. public static int CountOnes2(long num)
  162. {
  163. var count = 0;
  164. for (int i = 0; i < 64; i++)
  165. {
  166. // 检查 num 的最低位是否为1,如果是则 count 加1
  167. if ((num & 1) == 1)
  168. {
  169. count++;
  170. }
  171. // 将 num 向右移动一位,继续检查下一位
  172. num >>= 1;
  173. }
  174. return count;
  175. }
  176. /// <summary>
  177. /// 获取下一个索引,超出范围就获取0.
  178. /// </summary>
  179. /// <param name="curIndex">当前索引</param>
  180. /// <param name="arrLength">数组长度</param>
  181. /// <returns>返回下一个索引;返回true表示是新的一轮,返回false表示当轮</returns>
  182. public static (int, bool) GetArIndex(int curIndex, int arrLength)
  183. {
  184. int nextIndex;
  185. bool curIndexIsMax;
  186. if (curIndex == arrLength - 1)
  187. {
  188. // 当前索引已经是最大索引
  189. nextIndex = 0; // 重置获取索引为 0
  190. curIndexIsMax = true;
  191. }
  192. else
  193. {
  194. // 当前索引不是最大索引
  195. nextIndex = curIndex + 1; // 获取下一个索引
  196. curIndexIsMax = false;
  197. }
  198. return (nextIndex, curIndexIsMax);
  199. }
  200. /// <summary>
  201. /// 从issueNumbers里匹配下一个issueNumber
  202. /// </summary>
  203. /// <param name="issueNumber"></param>
  204. /// <param name="issueNumbers"></param>
  205. /// <returns></returns>
  206. public static int GetNextIssueNumber(int issueNumber, int[] issueNumbers)
  207. {
  208. // 如果整数数组为空,无法获取下一个期号,返回默认值 0
  209. if (issueNumbers == null || issueNumbers.Length == 0)
  210. {
  211. return 0;
  212. }
  213. // 查找 TeaPartyOpenCfgId 在整数数组中的索引
  214. int index = Array.IndexOf(issueNumbers, issueNumber);
  215. // 如果 TeaPartyOpenCfgId 不在整数数组中或者是整数数组的最后一个元素,则返回整数数组的第一个元素作为下一个期号
  216. if (index == -1 || index == issueNumbers.Length - 1)
  217. {
  218. return issueNumbers[0];
  219. }
  220. // 返回相邻的下一个元素作为下一个期号
  221. return issueNumbers[index + 1];
  222. }
  223. public static int ProgressCalculate(int haveCount, int totalCount)
  224. {
  225. if (haveCount > totalCount)
  226. {
  227. haveCount = totalCount;
  228. }
  229. float rate = haveCount * 100.0f / totalCount;
  230. int result;
  231. if (rate > 0 && rate <= 1)
  232. {
  233. result = 1;
  234. }
  235. else if (rate >= 99 && rate < 100)
  236. {
  237. result = 99;
  238. }
  239. else
  240. {
  241. result = (int)Math.Round(rate);
  242. }
  243. return result;
  244. }
  245. /// <summary>
  246. /// 假设为[1,2,3,4,5,6] 如果我知道3,然后需要返回上一条数据2. 如果我知道的是1,上面已经没有数据了,就返回0
  247. /// </summary>
  248. /// <param name="list"></param>
  249. /// <param name="target"></param>
  250. /// <returns></returns>
  251. public static int FindPreviousNumber(List<int> list, int target)
  252. {
  253. if (list.Contains(target))
  254. {
  255. int index = list.IndexOf(target);
  256. if (index > 0)
  257. {
  258. return list[index - 1];
  259. }
  260. }
  261. return 0;
  262. }
  263. //遍历数组dropTimesArr,并检查每个元素是否大于或等于appearNum
  264. public static int GetIndex(int[] dropTimesArr, int appearNum)
  265. {
  266. for (int i = 0; i < dropTimesArr.Length; i++)
  267. {
  268. if (dropTimesArr[i] >= appearNum)
  269. {
  270. return i;
  271. }
  272. }
  273. // 如果没有找到满足条件的元素,返回-1
  274. return -1;
  275. }
  276. public static int GetIndex(List<int> dropTimesArr, int appearNum)
  277. {
  278. for (int i = 0; i < dropTimesArr.Count; i++)
  279. {
  280. if (dropTimesArr[i] >= appearNum)
  281. {
  282. return i;
  283. }
  284. }
  285. // 如果没有找到满足条件的元素,返回-1
  286. return -1;
  287. }
  288. }
  289. }