hutool-python 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. hutool/__init__.py +174 -0
  2. hutool/cache/__init__.py +7 -0
  3. hutool/cache/cache_util.py +47 -0
  4. hutool/cache/fifo_cache.py +87 -0
  5. hutool/cache/lfu_cache.py +129 -0
  6. hutool/cache/lru_cache.py +93 -0
  7. hutool/cache/timed_cache.py +115 -0
  8. hutool/captcha/__init__.py +3 -0
  9. hutool/captcha/captcha_util.py +215 -0
  10. hutool/core/__init__.py +23 -0
  11. hutool/core/_base.py +61 -0
  12. hutool/core/bean.py +214 -0
  13. hutool/core/codec.py +111 -0
  14. hutool/core/coll.py +635 -0
  15. hutool/core/date.py +1024 -0
  16. hutool/core/exceptions.py +66 -0
  17. hutool/core/io/__init__.py +0 -0
  18. hutool/core/io/data_size_util.py +79 -0
  19. hutool/core/io/file_name_util.py +111 -0
  20. hutool/core/io/file_util.py +650 -0
  21. hutool/core/io/io_util.py +133 -0
  22. hutool/core/io/path_util.py +247 -0
  23. hutool/core/io/resource_util.py +137 -0
  24. hutool/core/map.py +933 -0
  25. hutool/core/math_util.py +105 -0
  26. hutool/core/net.py +288 -0
  27. hutool/core/text/__init__.py +0 -0
  28. hutool/core/text/csv_util.py +54 -0
  29. hutool/core/text/str_builder.py +224 -0
  30. hutool/core/text/unicode_util.py +58 -0
  31. hutool/core/tree.py +242 -0
  32. hutool/core/util/__init__.py +63 -0
  33. hutool/core/util/array_util.py +503 -0
  34. hutool/core/util/boolean_util.py +124 -0
  35. hutool/core/util/charset_util.py +60 -0
  36. hutool/core/util/class_util.py +136 -0
  37. hutool/core/util/coordinate_util.py +186 -0
  38. hutool/core/util/credit_code_util.py +110 -0
  39. hutool/core/util/desensitized_util.py +194 -0
  40. hutool/core/util/enum_util.py +94 -0
  41. hutool/core/util/escape_util.py +97 -0
  42. hutool/core/util/hash_util.py +243 -0
  43. hutool/core/util/hex_util.py +140 -0
  44. hutool/core/util/id_util.py +147 -0
  45. hutool/core/util/idcard_util.py +300 -0
  46. hutool/core/util/number_util.py +720 -0
  47. hutool/core/util/object_util.py +294 -0
  48. hutool/core/util/page_util.py +61 -0
  49. hutool/core/util/phone_util.py +140 -0
  50. hutool/core/util/random_util.py +112 -0
  51. hutool/core/util/re_util.py +231 -0
  52. hutool/core/util/reflect_util.py +135 -0
  53. hutool/core/util/runtime_util.py +89 -0
  54. hutool/core/util/str_util.py +2320 -0
  55. hutool/core/util/system_util.py +62 -0
  56. hutool/core/util/url_util.py +232 -0
  57. hutool/core/util/version_util.py +41 -0
  58. hutool/core/util/xml_util.py +158 -0
  59. hutool/core/util/zip_util.py +126 -0
  60. hutool/cron/__init__.py +4 -0
  61. hutool/cron/cron_pattern.py +123 -0
  62. hutool/cron/cron_util.py +115 -0
  63. hutool/crypto/__init__.py +5 -0
  64. hutool/crypto/digest_util.py +167 -0
  65. hutool/crypto/secure_util.py +311 -0
  66. hutool/crypto/sign_util.py +74 -0
  67. hutool/dfa/__init__.py +3 -0
  68. hutool/dfa/sensitive_util.py +114 -0
  69. hutool/extra/__init__.py +6 -0
  70. hutool/extra/emoji_util.py +90 -0
  71. hutool/extra/pinyin_util.py +44 -0
  72. hutool/extra/qr_code_util.py +58 -0
  73. hutool/extra/template_util.py +41 -0
  74. hutool/http/__init__.py +6 -0
  75. hutool/http/html_util.py +88 -0
  76. hutool/http/http_request.py +188 -0
  77. hutool/http/http_response.py +139 -0
  78. hutool/http/http_util.py +237 -0
  79. hutool/json_util.py +251 -0
  80. hutool/jwt_util.py +57 -0
  81. hutool/setting/__init__.py +5 -0
  82. hutool/setting/props_util.py +79 -0
  83. hutool/setting/setting_util.py +80 -0
  84. hutool/setting/yaml_util.py +45 -0
  85. hutool_python-1.0.0.dist-info/LICENSE +127 -0
  86. hutool_python-1.0.0.dist-info/METADATA +438 -0
  87. hutool_python-1.0.0.dist-info/RECORD +89 -0
  88. hutool_python-1.0.0.dist-info/WHEEL +5 -0
  89. hutool_python-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,720 @@
1
+ """
2
+ Python port of Java Hutool's NumberUtil.
3
+
4
+ 提供精确的加减乘除运算、四舍五入、数字格式化、数字判断等常用数字工具方法。
5
+ """
6
+
7
+ import decimal
8
+ import math
9
+ import random
10
+ import re
11
+ from decimal import Decimal, InvalidOperation
12
+ from typing import Final, List, Literal, Optional, Union
13
+
14
+ from .._base import DefaultParam
15
+ from .str_util import StrUtil
16
+
17
+ __all__ = [
18
+ "NumberUtil",
19
+ ]
20
+
21
+ # 数字工具类默认参数
22
+ DEFAULT_NUMBER_PARAM = DefaultParam()
23
+
24
+
25
+ class NumberUtil:
26
+ """
27
+ 数字工具类
28
+ """
29
+
30
+ # 默认除法运算精度
31
+ DEFAULT_DIV_SCALE: Final[int] = 10
32
+ # 零
33
+ ZERO: Final[Decimal] = Decimal("0")
34
+
35
+ @staticmethod
36
+ def add(*values: Union[int, float, str, None, Decimal]) -> Decimal:
37
+ """
38
+ 提供精确的加法运算
39
+ 如果传入多个值为None或者空,则返回0
40
+ :param values: 多个被加值
41
+ :return: 和
42
+ """
43
+ if not values:
44
+ return NumberUtil.ZERO
45
+ result = NumberUtil.ZERO
46
+ for value in values:
47
+ result += NumberUtil.to_decimal(value)
48
+ return result
49
+
50
+ @staticmethod
51
+ def sub(*values: Union[int, float, str, None, Decimal]) -> Decimal:
52
+ """
53
+ 提供精确的减法运算
54
+ 如果传入多个值为None或者空,则返回0
55
+ :param values: 多个被减值
56
+ :return: 差
57
+ """
58
+ if not values:
59
+ return NumberUtil.ZERO
60
+ result = NumberUtil.to_decimal(values[0])
61
+ for i in range(1, len(values)):
62
+ result -= NumberUtil.to_decimal(values[i])
63
+ return result
64
+
65
+ @staticmethod
66
+ def mul(*values: Union[int, float, str, None, Decimal]) -> Decimal:
67
+ """
68
+ 提供精确的乘法运算
69
+
70
+ 如果传入多个值为None或者空,则返回0
71
+
72
+ :param values: 多个被乘值
73
+ :return: 积
74
+ """
75
+ if not values or any(v is None for v in values):
76
+ return NumberUtil.ZERO
77
+ result = NumberUtil.to_decimal(values[0])
78
+ for i in range(1, len(values)):
79
+ result *= NumberUtil.to_decimal(values[i])
80
+ return result
81
+
82
+ @staticmethod
83
+ def div(
84
+ v1: Union[int, float, str, None, Decimal],
85
+ v2: Union[int, float, str, Decimal],
86
+ scale: Union[int, Decimal] = DEFAULT_DIV_SCALE,
87
+ rounding: str = decimal.ROUND_HALF_UP,
88
+ ) -> Decimal:
89
+ """
90
+ 提供(相对)精确的除法运算,当发生除不尽的情况时,由scale指定精确度
91
+ :param v1: 被除数
92
+ :param v2: 除数
93
+ :param scale: 精确度,如果为负值,取绝对值, 如果为Decimal, 需要为Decimal('0.00')格式
94
+ :param rounding: 保留小数的模式
95
+ :return: 两个参数的商
96
+ """
97
+ assert v2 is not None, "Divisor must be not none!"
98
+ if v1 is None:
99
+ return NumberUtil.ZERO
100
+
101
+ v1 = NumberUtil.to_decimal(v1)
102
+ v2 = NumberUtil.to_decimal(v2)
103
+ return NumberUtil.round(v1 / v2, scale, rounding=rounding)
104
+
105
+ @staticmethod
106
+ def ceil_div(v1: int, v2: int) -> int:
107
+ """
108
+ 除法, 向上取整
109
+ :param v1: 被除数
110
+ :param v2: 除数
111
+ :return: 两个参数的商
112
+ """
113
+ return math.ceil(v1 / v2)
114
+
115
+ @staticmethod
116
+ def round(
117
+ number: Union[int, float, str, None, Decimal],
118
+ scale: Union[int, Decimal],
119
+ rounding: str = decimal.ROUND_HALF_UP,
120
+ ) -> Decimal:
121
+ """
122
+ 保留固定位数小数
123
+ :param number: 数字值
124
+ :param scale: 精确度,如果为负值,取绝对值, 如果为Decimal, 需要为Decimal('0.00')格式
125
+ :param rounding: 保留小数的模式
126
+ :return: 新值
127
+ """
128
+ number = NumberUtil.to_decimal(number)
129
+
130
+ if isinstance(scale, int):
131
+ if scale < 0:
132
+ scale = -scale
133
+ scale_num = scale
134
+ scale = Decimal("0." + "0" * scale)
135
+ else:
136
+ scale_num = len(str(scale)) - 2
137
+
138
+ if decimal.getcontext().prec < scale_num:
139
+ decimal.getcontext().prec = scale_num
140
+
141
+ return number.quantize(scale, rounding=rounding)
142
+
143
+ @staticmethod
144
+ def round_str(
145
+ number: Union[int, float, str, None, Decimal],
146
+ scale: Union[int, Decimal],
147
+ rounding: str = decimal.ROUND_HALF_UP,
148
+ ) -> str:
149
+ """
150
+ 保留固定位数小数
151
+ :param number: 数字值
152
+ :param scale: 精确度,如果为负值,取绝对值, 如果为Decimal, 需要为Decimal('0.00')格式
153
+ :param rounding: 保留小数的模式
154
+ :return: 新值
155
+ """
156
+ return f"{NumberUtil.round(number, scale, rounding=rounding).normalize():f}"
157
+
158
+ @staticmethod
159
+ def round_half_even(
160
+ number: Union[int, float, str, None, Decimal],
161
+ scale: Union[int, Decimal],
162
+ ) -> Decimal:
163
+ """
164
+ 四舍六入五成双计算法
165
+ 四舍六入五成双是一种比较精确比较科学的计数保留法,是一种数字修约规则。
166
+ 算法规则:
167
+ 四舍六入五考虑,
168
+ 五后非零就进一,
169
+ 五后皆零看奇偶,
170
+ 五前为偶应舍去,
171
+ 五前为奇要进一。
172
+ :param number: 需要科学计算的数据
173
+ :param scale: 精确度,如果为负值,取绝对值, 如果为Decimal, 需要为Decimal('0.00')格式
174
+ :return: 结果
175
+ """
176
+ return NumberUtil.round(number, scale, rounding=decimal.ROUND_HALF_EVEN)
177
+
178
+ @staticmethod
179
+ def round_down(
180
+ number: Union[int, float, str, None, Decimal],
181
+ scale: Union[int, Decimal],
182
+ ) -> Decimal:
183
+ """
184
+ 保留固定小数位数,舍去多余位数
185
+ :param number: 需要科学计算的数据
186
+ :param scale: 保留的小数位
187
+ :return: 结果
188
+ """
189
+ return NumberUtil.round(number, scale, rounding=decimal.ROUND_DOWN)
190
+
191
+ @staticmethod
192
+ def decimal_format(pattern: str, value: Union[int, float, str, None, Decimal]) -> str:
193
+ """格式化
194
+
195
+ :param pattern: 格式,例如:
196
+
197
+ - ``'{:.2f}'`` 保留两位小数
198
+ - ``'{:.0f}'`` 取所有整数部分
199
+ - ``'{:.2%}'`` 以百分比方式计数,并取两位小数
200
+ - ``'{:.5e}'`` 显示为科学计数法,并取五位小数
201
+ - ``'{:,}'`` 每三位以逗号进行分隔
202
+
203
+ :param value: 值
204
+ :return: 格式化后的值
205
+ """
206
+ assert NumberUtil.is_valid(value), "value is NaN or Infinite!"
207
+ return pattern.format(NumberUtil.to_decimal(value))
208
+
209
+ @staticmethod
210
+ def decimal_format_money(value: float) -> str:
211
+ """
212
+ 格式化金额输出,每三位用逗号分隔
213
+ :param value: 金额
214
+ :return: 格式化后的值
215
+ """
216
+ return NumberUtil.decimal_format("{:,.2f}", value)
217
+
218
+ @staticmethod
219
+ def format_percent(number: float, scale: int) -> str:
220
+ """
221
+ 格式化百分比,小数采用四舍五入方式
222
+ :param number: 值
223
+ :param scale: 保留小数位数
224
+ :return: 百分比
225
+ """
226
+ return NumberUtil.decimal_format("{:." + str(scale) + "%}", NumberUtil.round(number, scale + 2))
227
+
228
+ @staticmethod
229
+ def is_number(string: str) -> bool:
230
+ """
231
+ 是否为数字,支持包括:
232
+ 1、10进制
233
+ 2、16进制数字(0x开头, 0x1aF)
234
+ 3、科学计数法形式(1234E3)
235
+ 4、正负数标识形式(+123、-234)
236
+ :param string: 字符串值
237
+ :return: 是否为数字
238
+ """
239
+ if StrUtil.is_blank(string):
240
+ return False
241
+ pattern = r"^[+-]?((0[xX][0-9a-fA-F]+)|((\d+\.?\d*|\.\d+)([eE][+-]?\d+)?))$"
242
+ return re.match(pattern, string) is not None
243
+
244
+ @staticmethod
245
+ def is_int(string: Union[str, None]) -> bool:
246
+ """
247
+ 判断string是否是整数
248
+ :param string: 字符串值
249
+ :return: 是否为整数
250
+ """
251
+ if StrUtil.is_blank(string):
252
+ return False
253
+ try:
254
+ int(string)
255
+ except ValueError:
256
+ return False
257
+ return True
258
+
259
+ @staticmethod
260
+ def is_float(string: str) -> bool:
261
+ """
262
+ 判断字符串是否是浮点数
263
+ :param string: 字符串值
264
+ :return: 是否是浮点数
265
+ """
266
+ if StrUtil.is_blank(string):
267
+ return False
268
+ try:
269
+ float(string)
270
+ except ValueError:
271
+ return False
272
+ return "." in string
273
+
274
+ @staticmethod
275
+ def is_primes(n: int) -> bool:
276
+ """
277
+ 是否是质数(素数)
278
+ 质数表的质数又称素数。指整数在一个大于1的自然数中,除了1和此整数自身外,没法被其他自然数整除的数。
279
+ :param n: 数字
280
+ :return: 是否是质数
281
+ """
282
+ assert n > 1, "The number must be > 1"
283
+ for i in range(2, int(math.sqrt(n)) + 1):
284
+ if n % i == 0:
285
+ return False
286
+ return True
287
+
288
+ @staticmethod
289
+ def generate_random_number(begin: int, end: int, size: int, seed: Optional[int] = None) -> List[int]:
290
+ """
291
+ 生成不重复随机数 根据给定的最小数字和最大数字,以及随机数的个数,产生指定的不重复的列表
292
+ :param begin: 最小数字(包含该数)
293
+ :param end: 最大数字(不包含该数)
294
+ :param size: 指定产生随机数的个数
295
+ :param seed: 随机种子
296
+ :return: 随机int列表
297
+ """
298
+ return random.Random(seed).sample(list(range(begin, end)), size)
299
+
300
+ @staticmethod
301
+ def factorial(start: int, end: int = 0) -> int:
302
+ """
303
+ 计算阶乘
304
+ factorial(start, end) = start * (start - 1) * ... * (end + 1)
305
+ :param start: 阶乘起始(包含)
306
+ :param end: 阶乘结束,必须小于起始(不包括)
307
+ :return: 结果
308
+ """
309
+ assert start is not None, "Factorial start must be not null!"
310
+ assert end is not None, "Factorial end must be not null!"
311
+ if start < 0 or end < 0:
312
+ raise ValueError(f"Factorial start and end both must be > 0, but got start={start}, end={end}")
313
+
314
+ if start == 0 or start == end:
315
+ return 1
316
+ if start < end:
317
+ return 0
318
+ if end < 1:
319
+ end = 1
320
+
321
+ result = start
322
+ end += 1
323
+ while start > end:
324
+ start -= 1
325
+ result *= start
326
+ return result
327
+
328
+ @staticmethod
329
+ def divisor(m: int, n: int) -> int:
330
+ """
331
+ 最大公约数
332
+ :param m: 第一个值
333
+ :param n: 第二个值
334
+ :return: 最大公约数
335
+ """
336
+ while m % n != 0:
337
+ temp = m % n
338
+ m = n
339
+ n = temp
340
+ return n
341
+
342
+ @staticmethod
343
+ def multiple(m: int, n: int) -> int:
344
+ """
345
+ 最小公倍数
346
+ :param m: 第一个值
347
+ :param n: 第二个值
348
+ :return: 最小公倍数
349
+ """
350
+ return m * n // NumberUtil.divisor(m, n)
351
+
352
+ @staticmethod
353
+ def get_binary_str(number: int) -> str:
354
+ """
355
+ 获得数字对应的二进制字符串
356
+ :param number: 数字
357
+ :return: 二进制字符串
358
+ """
359
+ return bin(number)
360
+
361
+ @staticmethod
362
+ def binary_to_int(binary_str: str) -> int:
363
+ """
364
+ 二进制转int
365
+ :param binary_str: 二进制字符串
366
+ :return: int
367
+ """
368
+ return int(binary_str, 2)
369
+
370
+ @staticmethod
371
+ def compare(num1: Union[int, float, str, Decimal], num2: Union[int, float, str, Decimal]) -> int:
372
+ """
373
+ 比较两个值的大小
374
+ :param num1: 第一个值
375
+ :param num2: 第二个值
376
+ :return: x==y返回0,x<y返回小于0的数,x>y返回大于0的数
377
+ """
378
+ assert num1 is not None, "first value must not be none!"
379
+ assert num2 is not None, "second value must not be none!"
380
+ return int(NumberUtil.to_decimal(num1).compare(NumberUtil.to_decimal(num2)))
381
+
382
+ @staticmethod
383
+ def is_greater(num1: Union[int, float, str, Decimal], num2: Union[int, float, str, Decimal]) -> bool:
384
+ """
385
+ 比较大小,参数1 > 参数2 返回True
386
+ :param num1: 数字1
387
+ :param num2: 数字2
388
+ :return: 是否大于
389
+ """
390
+ return NumberUtil.compare(num1, num2) > 0
391
+
392
+ @staticmethod
393
+ def is_greater_or_equal(num1: Union[int, float, str, Decimal], num2: Union[int, float, str, Decimal]) -> bool:
394
+ """
395
+ 比较大小,参数1 >= 参数2 返回True
396
+ :param num1: 数字1
397
+ :param num2: 数字2
398
+ :return: 是否大于等于
399
+ """
400
+ return NumberUtil.compare(num1, num2) >= 0
401
+
402
+ @staticmethod
403
+ def is_less(num1: Union[int, float, str, Decimal], num2: Union[int, float, str, Decimal]) -> bool:
404
+ """
405
+ 比较大小,参数1 < 参数2 返回True
406
+ :param num1: 数字1
407
+ :param num2: 数字2
408
+ :return: 是否小于
409
+ """
410
+ return NumberUtil.compare(num1, num2) < 0
411
+
412
+ @staticmethod
413
+ def is_less_or_equal(num1: Union[int, float, str, Decimal], num2: Union[int, float, str, Decimal]) -> bool:
414
+ """
415
+ 比较大小,参数1 <= 参数2 返回True
416
+ :param num1: 数字1
417
+ :param num2: 数字2
418
+ :return: 是否小于等于
419
+ """
420
+ return NumberUtil.compare(num1, num2) <= 0
421
+
422
+ @staticmethod
423
+ def is_in(
424
+ value: Union[int, float, str, Decimal],
425
+ min_include: Union[int, float, str, Decimal],
426
+ max_include: Union[int, float, str, Decimal],
427
+ ) -> bool:
428
+ """
429
+ 检查值是否在指定范围内
430
+ :param value: 值
431
+ :param min_include: 最小值(包含)
432
+ :param max_include: 最大值(包含)
433
+ :return: 经过检查后的值
434
+ """
435
+ assert value is not None, "value must be not none!"
436
+ assert min_include is not None, "min_include must be not none!"
437
+ assert max_include is not None, "max_include must be not none!"
438
+ return NumberUtil.is_greater_or_equal(value, min_include) and NumberUtil.is_less_or_equal(value, max_include)
439
+
440
+ @staticmethod
441
+ def equals(num1: Union[int, float, str, Decimal], num2: Union[int, float, str, Decimal]) -> bool:
442
+ """
443
+ 比较大小,值相等 返回True
444
+ :param num1: 数字1
445
+ :param num2: 数字2
446
+ :return: 是否相等
447
+ """
448
+ return NumberUtil.compare(num1, num2) == 0
449
+
450
+ @staticmethod
451
+ def min(*numbers: Union[int, float, str, Decimal]) -> Decimal:
452
+ """
453
+ 取最小值
454
+ :param numbers: 数字数组
455
+ :return: 最小值
456
+ """
457
+ assert bool(numbers), "Number array must not empty!"
458
+ nums = [NumberUtil.to_decimal(num) for num in numbers]
459
+ return min(*nums)
460
+
461
+ @staticmethod
462
+ def max(*numbers: Union[int, float, str, Decimal]) -> Decimal:
463
+ """
464
+ 取最大值
465
+ :param numbers: 数字数组
466
+ :return: 最大值
467
+ """
468
+ assert bool(numbers), "Number array must not empty!"
469
+ nums = [NumberUtil.to_decimal(num) for num in numbers]
470
+ return max(*nums)
471
+
472
+ @staticmethod
473
+ def to_str(
474
+ number: Union[int, float, Decimal],
475
+ normalize: bool = True,
476
+ default_value: Optional[str] = None,
477
+ ) -> str:
478
+ """
479
+ 数字转字符串
480
+ :param number: 数字
481
+ :param normalize: 是否去除末尾多余0,例如5.0返回5
482
+ :param default_value: 如果number参数为None,返回此默认值
483
+ :return: 字符串
484
+ """
485
+ if number is None:
486
+ if default_value is None:
487
+ raise ValueError("Number is None!")
488
+ else:
489
+ return default_value
490
+
491
+ assert NumberUtil.is_valid(number), "Number is non-finite!"
492
+ if normalize:
493
+ return f"{NumberUtil.to_decimal(number).normalize():f}"
494
+ return str(number)
495
+
496
+ @staticmethod
497
+ def to_decimal(number: Union[int, float, str, None, Decimal]) -> Decimal:
498
+ """
499
+ 转成Decimal
500
+ float有精度问题,转换为字符串后再转换
501
+ None或""或空白符转换为0
502
+ :param number: 数字
503
+ :return: Decimal
504
+ """
505
+ if number is None:
506
+ return NumberUtil.ZERO
507
+
508
+ if isinstance(number, int):
509
+ return Decimal(number)
510
+ elif isinstance(number, Decimal):
511
+ return number
512
+
513
+ number = str(number)
514
+ if StrUtil.is_blank(number):
515
+ return NumberUtil.ZERO
516
+
517
+ try:
518
+ return Decimal(number)
519
+ except InvalidOperation:
520
+ # 忽略解析错误
521
+ pass
522
+
523
+ return NumberUtil.to_decimal(str(NumberUtil.parse_float(number)))
524
+
525
+ @staticmethod
526
+ def count(total: int, part: int) -> int:
527
+ """
528
+ 计算等份个数
529
+ :param total: 总数
530
+ :param part: 每份的个数
531
+ :return: 分成了几份
532
+ """
533
+ return (total // part) if total % part == 0 else (total // part + 1)
534
+
535
+ @staticmethod
536
+ def none_to_zero(number: Union[int, float, str, Decimal]) -> Union[int, float, str, Decimal]:
537
+ """
538
+ 空转0
539
+ :param number: 参数
540
+ :return: 参数为空时返回0的值
541
+ """
542
+ if number is not None:
543
+ return number
544
+
545
+ if isinstance(number, int):
546
+ return 0
547
+ elif isinstance(number, float):
548
+ return 0.0
549
+ elif isinstance(number, str):
550
+ return "0"
551
+ elif isinstance(number, Decimal):
552
+ return NumberUtil.ZERO
553
+ return 0
554
+
555
+ @staticmethod
556
+ def zero2one(value: int) -> int:
557
+ """
558
+ 如果给定值为0,返回1,否则返回原值
559
+ :param value: 值
560
+ :return: 1或非0值
561
+ """
562
+ return 1 if value == 0 else value
563
+
564
+ @staticmethod
565
+ def is_beside(number1: Union[int, float, str, Decimal], number2: Union[int, float, str, Decimal]) -> bool:
566
+ """
567
+ 判断两个数字是否相邻,例如1和2相邻,1和3不相邻
568
+ 判断方法为做差取绝对值判断是否为1
569
+ :param number1: 数字1
570
+ :param number2: 数字2
571
+ :return: 是否相邻
572
+ """
573
+ return math.fabs(NumberUtil.to_decimal(number1) - NumberUtil.to_decimal(number2)) == 1
574
+
575
+ @staticmethod
576
+ def part_value(total: int, part_count: int, is_plus_one_when_has_rem: bool = True) -> int:
577
+ """
578
+ 把给定的总数平均分成N份,返回每份的个数
579
+ 如果is_plus_one_when_has_rem为True,则当除以分数有余数时每份+1,否则丢弃余数部分
580
+ :param total: 总数
581
+ :param part_count: 份数
582
+ :param is_plus_one_when_has_rem: 在有余数时是否每份+1
583
+ :return: 每份的个数
584
+ """
585
+ pv = total // part_count
586
+ if is_plus_one_when_has_rem and total % part_count > 0:
587
+ pv += 1
588
+ return pv
589
+
590
+ @staticmethod
591
+ def pow(number: Union[int, float, str, Decimal], n: int) -> Decimal:
592
+ """
593
+ 提供精确的幂运算
594
+ :param number: 底数
595
+ :param n: 指数
596
+ :return: 幂的积
597
+ """
598
+ return NumberUtil.to_decimal(number) ** n
599
+
600
+ @staticmethod
601
+ def is_power_of_two(n: int) -> bool:
602
+ """
603
+ 判断一个整数是否是2的幂
604
+ :param n: 待验证的整数
605
+ :return: 如果n是2的幂返回True, 反之返回False
606
+ """
607
+ return n > 0 and n & (n - 1) == 0
608
+
609
+ @staticmethod
610
+ def parse_int(number_str: str, default_value: Union[int, DefaultParam, None] = DEFAULT_NUMBER_PARAM) -> int:
611
+ """
612
+ 解析转换数字字符串为int型数字,规则如下:
613
+ 1、0x开头的视为16进制数字
614
+ 2、0开头的忽略开头的0
615
+ 3、其它情况按照10进制转换
616
+ 4、空串返回默认值
617
+ 5、.123形式返回0(按照小于0的小数对待)
618
+ 6、123.56截取小数点之前的数字,忽略小数部分
619
+ 7、返回默认值
620
+ :param number_str: 数字,支持0x开头、0开头和普通十进制
621
+ :param default_value: 返回默认值
622
+ :return: int
623
+ """
624
+ is_default = isinstance(default_value, DefaultParam)
625
+ if StrUtil.is_blank(number_str):
626
+ return 0 if is_default else default_value
627
+
628
+ try:
629
+ if StrUtil.start_with_ignore_case(number_str, "0x"):
630
+ return int(number_str, 16)
631
+ if StrUtil.contains(number_str, "."):
632
+ number_str = float(number_str)
633
+ return int(number_str)
634
+ except ValueError as ve:
635
+ if is_default:
636
+ raise ve
637
+ else:
638
+ return default_value
639
+
640
+ @staticmethod
641
+ def parse_float(number_str: str, default_value: Union[int, DefaultParam, None] = DEFAULT_NUMBER_PARAM) -> float:
642
+ """
643
+ 解析转换数字字符串为float型数字,规则如下:
644
+ 1、0开头的忽略开头的0
645
+ 2、空串返回默认值
646
+ 3、其它情况按照10进制转换
647
+ :param number_str: 数字,支持0x开头、0开头和普通十进制
648
+ :param default_value: 返回默认值
649
+ :return: float
650
+ """
651
+ is_default = isinstance(default_value, DefaultParam)
652
+ if StrUtil.is_blank(number_str):
653
+ return 0 if is_default else default_value
654
+ try:
655
+ if StrUtil.start_with_ignore_case(number_str, "0x"):
656
+ return float.fromhex(number_str)
657
+ return float(number_str)
658
+ except ValueError as ve:
659
+ if is_default:
660
+ raise ve
661
+ else:
662
+ return default_value
663
+
664
+ @staticmethod
665
+ def to_bytes(
666
+ value: int,
667
+ length: Optional[int] = None,
668
+ byteorder: Literal["little", "big"] = "big",
669
+ signed: bool = True,
670
+ ) -> bytes:
671
+ """
672
+ int值转bytes
673
+ :param value: 值
674
+ :param length: bytes长度
675
+ :param byteorder: 默认大端字节序(高位字节在前,低位字节在后)
676
+ :param signed: 是否带符号
677
+ :return: bytes
678
+ """
679
+ if length is None:
680
+ length = (value.bit_length() + 7) // 8
681
+ return value.to_bytes(length, byteorder, signed=signed)
682
+
683
+ @staticmethod
684
+ def to_int(value: bytes, byteorder: Literal["little", "big"] = "big", signed: bool = True) -> int:
685
+ """
686
+ bytes转int
687
+ :param value: bytes
688
+ :param byteorder: 默认大端字节序(高位字节在前,低位字节在后)
689
+ :param signed: 是否带符号
690
+ :return: int
691
+ """
692
+ return int.from_bytes(value, byteorder, signed=signed)
693
+
694
+ @staticmethod
695
+ def is_valid(number: Union[int, float, Decimal]) -> bool:
696
+ """
697
+ 检查是否为有效的数字
698
+ 检查是否为无限大,或者Not a Number
699
+ :param number: 被检查的数字
700
+ :return: 检查结果,非数字类型和None将返回False
701
+ """
702
+ return not (number is None or math.isinf(number) or math.isnan(number))
703
+
704
+ @staticmethod
705
+ def is_odd(num: int) -> bool:
706
+ """
707
+ 检查是否为奇数
708
+ :param num: 被判断的数值
709
+ :return: 是否是奇数
710
+ """
711
+ return (num & 1) == 1
712
+
713
+ @staticmethod
714
+ def is_even(num: int) -> bool:
715
+ """
716
+ 检查是否为偶数
717
+ :param num: 被判断的数值
718
+ :return: 是否是偶数
719
+ """
720
+ return not NumberUtil.is_odd(num)