tretool 0.2.1__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.
tretool/mathlib.py ADDED
@@ -0,0 +1,620 @@
1
+ """
2
+ PurePythonMath - 纯Python实现的完整数学函数库
3
+ 包含所有基础数学运算、三角函数、双曲函数、指数对数函数、特殊函数等
4
+ """
5
+
6
+ from typing import Union, Tuple, Optional
7
+ from decimal import Decimal, getcontext, Context
8
+ import sys
9
+ import itertools
10
+
11
+ # ==================== 类型定义 ====================
12
+ AnyNum = Union[int, float, Decimal]
13
+ PrecisionType = Union[int, float, Decimal, None]
14
+
15
+ # ==================== 常数定义 ====================
16
+ PI = Decimal('3.14159265358979323846264338327950288419716939937510')
17
+ E = Decimal('2.71828182845904523536028747135266249775724709369995')
18
+ INF = float('inf')
19
+ NAN = float('nan')
20
+ PHI = Decimal('1.61803398874989484820458683436563811772030917980576') # 黄金比例
21
+ GAMMA = Decimal('0.57721566490153286060651209008240243104215933593992') # 欧拉-马歇罗尼常数
22
+
23
+ # ==================== 配置管理 ====================
24
+ class MathConfig:
25
+ _precision = 15
26
+ _rounding = 'ROUND_HALF_EVEN'
27
+
28
+ @classmethod
29
+ def set_precision(cls, prec: int):
30
+ """设置全局计算精度(小数位数)"""
31
+ cls._precision = prec
32
+ getcontext().prec = prec + 2 # Decimal保留额外位数
33
+
34
+ @classmethod
35
+ def set_rounding(cls, mode: str):
36
+ """设置舍入模式(同Decimal模块)"""
37
+ cls._rounding = mode
38
+ getcontext().rounding = mode
39
+
40
+ # 初始化配置
41
+ MathConfig.set_precision(15)
42
+
43
+ # ==================== 辅助函数 ====================
44
+ def _convert_to_decimal(x: AnyNum, prec: PrecisionType = None) -> Decimal:
45
+ """将输入转换为Decimal,应用指定精度"""
46
+ if isinstance(x, Decimal):
47
+ return x
48
+ ctx = Context(prec=prec + 2 if prec else getcontext().prec)
49
+ return Decimal(str(float(x))).quantize(Decimal(10) ** -ctx.prec)
50
+
51
+ def _keep_type(x: AnyNum, result: Decimal, prec: PrecisionType = None) -> AnyNum:
52
+ """保持输入类型输出"""
53
+ if prec is not None or isinstance(x, Decimal):
54
+ return +result # 应用当前精度
55
+ return float(result)
56
+
57
+ # ==================== 基本运算 ====================
58
+ def sqrt(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
59
+ """平方根(牛顿迭代法)"""
60
+ if isinstance(x, Decimal) or prec is not None:
61
+ return _decimal_sqrt(x, prec)
62
+
63
+ if x < 0:
64
+ raise ValueError("math domain error")
65
+ if x == 0:
66
+ return 0.0
67
+
68
+ guess = max(float(x), 1)
69
+ while True:
70
+ new_guess = (guess + x / guess) / 2
71
+ if abs(new_guess - guess) < 1e-15:
72
+ return new_guess
73
+ guess = new_guess
74
+
75
+ def _decimal_sqrt(x: Decimal, prec: PrecisionType = None) -> Decimal:
76
+ """高精度Decimal版平方根"""
77
+ ctx = Context(prec=prec + 2 if prec else getcontext().prec)
78
+ if x < 0:
79
+ raise ValueError("math domain error")
80
+ if x == 0:
81
+ return Decimal(0)
82
+
83
+ guess = max(x, Decimal(1))
84
+ while True:
85
+ new_guess = (guess + x / guess) / 2
86
+ if abs(new_guess - guess) < Decimal(10) ** (-ctx.prec + 1):
87
+ return +new_guess
88
+ guess = new_guess
89
+
90
+ def power(base: AnyNum, exponent: AnyNum, prec: PrecisionType = None) -> AnyNum:
91
+ """幂运算 base^exponent"""
92
+ if isinstance(base, Decimal) or isinstance(exponent, Decimal) or prec is not None:
93
+ return _decimal_power(base, exponent, prec)
94
+
95
+ if isinstance(exponent, int):
96
+ return _int_power(base, exponent)
97
+ else:
98
+ return exp(exponent * ln(base))
99
+
100
+ def _decimal_power(base: AnyNum, exponent: AnyNum, prec: PrecisionType = None) -> Decimal:
101
+ """高精度Decimal版幂运算"""
102
+ base_dec = _convert_to_decimal(base, prec)
103
+ exponent_dec = _convert_to_decimal(exponent, prec)
104
+
105
+ if exponent_dec == 0:
106
+ return Decimal(1)
107
+ if base_dec == 0:
108
+ if exponent_dec < 0:
109
+ raise ValueError("0 cannot be raised to a negative power")
110
+ return Decimal(0)
111
+
112
+ return _decimal_exp(exponent_dec * _decimal_ln(base_dec, prec), prec)
113
+
114
+ def _int_power(base: AnyNum, n: int) -> AnyNum:
115
+ """快速幂算法(仅整数指数)"""
116
+ if n == 0:
117
+ return type(base)(1)
118
+ if n < 0:
119
+ return 1 / _int_power(base, -n)
120
+
121
+ result = type(base)(1)
122
+ while n > 0:
123
+ if n % 2 == 1:
124
+ result *= base
125
+ base *= base
126
+ n //= 2
127
+ return result
128
+
129
+ # ==================== 指数对数函数 ====================
130
+ def exp(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
131
+ """指数函数 e^x"""
132
+ if isinstance(x, Decimal) or prec is not None:
133
+ return _decimal_exp(x, prec)
134
+
135
+ result = 1.0
136
+ term = 1.0
137
+ for n in range(1, 100):
138
+ term *= x / n
139
+ result += term
140
+ if abs(term) < 1e-15:
141
+ break
142
+ return result
143
+
144
+ def _decimal_exp(x: Decimal, prec: PrecisionType = None) -> Decimal:
145
+ """高精度Decimal版指数函数"""
146
+ ctx = Context(prec=prec + 2 if prec else getcontext().prec)
147
+ result = Decimal(1)
148
+ term = Decimal(1)
149
+ n = 1
150
+
151
+ while True:
152
+ term *= x / Decimal(n)
153
+ result += term
154
+ if abs(term) < Decimal(10) ** (-ctx.prec + 1):
155
+ return +result
156
+ n += 1
157
+
158
+ def ln(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
159
+ """自然对数 ln(x)"""
160
+ if isinstance(x, Decimal) or prec is not None:
161
+ return _decimal_ln(x, prec)
162
+
163
+ if x <= 0:
164
+ raise ValueError("math domain error")
165
+
166
+ # 调整x到收敛区间(0.5, 2)
167
+ n = 0
168
+ while x > 2:
169
+ x /= float(E)
170
+ n += 1
171
+ while x < 0.5:
172
+ x *= float(E)
173
+ n -= 1
174
+
175
+ # 泰勒展开
176
+ x -= 1
177
+ result = 0.0
178
+ sign = 1
179
+ for k in range(1, 100):
180
+ term = sign * (x ** k) / k
181
+ result += term
182
+ sign *= -1
183
+ if abs(term) < 1e-15:
184
+ break
185
+ return result + n
186
+
187
+ def _decimal_ln(x: Decimal, prec: PrecisionType = None) -> Decimal:
188
+ """高精度Decimal版自然对数"""
189
+ ctx = Context(prec=prec + 2 if prec else getcontext().prec)
190
+ if x <= 0:
191
+ raise ValueError("math domain error")
192
+
193
+ n = 0
194
+ while x > 2:
195
+ x /= E
196
+ n += 1
197
+ while x < Decimal('0.5'):
198
+ x *= E
199
+ n -= 1
200
+
201
+ x -= Decimal(1)
202
+ result = Decimal(0)
203
+ sign = Decimal(1)
204
+ for k in range(1, ctx.prec * 2):
205
+ term = sign * (x ** k) / k
206
+ result += term
207
+ sign *= -1
208
+ if abs(term) < Decimal(10) ** (-ctx.prec + 1):
209
+ break
210
+ return +(result + n)
211
+
212
+ def log(base: AnyNum, x: AnyNum, prec: PrecisionType = None) -> AnyNum:
213
+ """对数函数 logₐ(x)"""
214
+ if base <= 0 or base == 1 or x <= 0:
215
+ raise ValueError("math domain error")
216
+
217
+ if isinstance(base, Decimal) or isinstance(x, Decimal) or prec is not None:
218
+ base_dec = _convert_to_decimal(base, prec)
219
+ x_dec = _convert_to_decimal(x, prec)
220
+ return _decimal_ln(x_dec, prec) / _decimal_ln(base_dec, prec)
221
+
222
+ return ln(x) / ln(base)
223
+
224
+ # ==================== 三角函数 ====================
225
+ def sin(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
226
+ """正弦函数"""
227
+ if isinstance(x, Decimal) or prec is not None:
228
+ return _decimal_sin(x, prec)
229
+
230
+ x = x % (2 * float(PI))
231
+ if x > float(PI):
232
+ x -= 2 * float(PI)
233
+
234
+ result = 0.0
235
+ term = x
236
+ n = 1
237
+ for _ in range(100):
238
+ result += term
239
+ term *= -x * x / ((2 * n) * (2 * n + 1))
240
+ if abs(term) < 1e-15:
241
+ break
242
+ n += 1
243
+ return result
244
+
245
+ def _decimal_sin(x: Decimal, prec: PrecisionType = None) -> Decimal:
246
+ """高精度Decimal版正弦函数"""
247
+ ctx = Context(prec=prec + 2 if prec else getcontext().prec)
248
+ x = x % (2 * PI)
249
+ if x > PI:
250
+ x -= 2 * PI
251
+
252
+ result = Decimal(0)
253
+ term = x
254
+ n = 1
255
+ while True:
256
+ result += term
257
+ term *= -x * x / (Decimal(2 * n) * Decimal(2 * n + 1))
258
+ if abs(term) < Decimal(10) ** (-ctx.prec + 1):
259
+ break
260
+ n += 1
261
+ return +result
262
+
263
+ def cos(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
264
+ """余弦函数"""
265
+ if isinstance(x, Decimal) or prec is not None:
266
+ return _decimal_cos(x, prec)
267
+
268
+ x = x % (2 * float(PI))
269
+ if x > float(PI):
270
+ x -= 2 * float(PI)
271
+
272
+ result = 1.0
273
+ term = 1.0
274
+ n = 1
275
+ for _ in range(100):
276
+ term *= -x * x / ((2 * n - 1) * (2 * n))
277
+ result += term
278
+ if abs(term) < 1e-15:
279
+ break
280
+ n += 1
281
+ return result
282
+
283
+ def _decimal_cos(x: Decimal, prec: PrecisionType = None) -> Decimal:
284
+ """高精度Decimal版余弦函数"""
285
+ ctx = Context(prec=prec + 2 if prec else getcontext().prec)
286
+ x = x % (2 * PI)
287
+ if x > PI:
288
+ x -= 2 * PI
289
+
290
+ result = Decimal(1)
291
+ term = Decimal(1)
292
+ n = 1
293
+ while True:
294
+ term *= -x * x / (Decimal(2 * n - 1) * Decimal(2 * n))
295
+ result += term
296
+ if abs(term) < Decimal(10) ** (-ctx.prec + 1):
297
+ break
298
+ n += 1
299
+ return +result
300
+
301
+ def tan(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
302
+ """正切函数"""
303
+ if isinstance(x, Decimal) or prec is not None:
304
+ c = _decimal_cos(x, prec)
305
+ if abs(c) < Decimal(10) ** (-getcontext().prec + 1):
306
+ raise ValueError("math domain error")
307
+ return _decimal_sin(x, prec) / c
308
+
309
+ c = cos(x)
310
+ if abs(c) < 1e-10:
311
+ raise ValueError("math domain error")
312
+ return sin(x) / c
313
+
314
+ def cot(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
315
+ """余切函数"""
316
+ if isinstance(x, Decimal) or prec is not None:
317
+ s = _decimal_sin(x, prec)
318
+ if abs(s) < Decimal(10) ** (-getcontext().prec + 1):
319
+ raise ValueError("math domain error")
320
+ return _decimal_cos(x, prec) / s
321
+
322
+ s = sin(x)
323
+ if abs(s) < 1e-10:
324
+ raise ValueError("math domain error")
325
+ return cos(x) / s
326
+
327
+ # ==================== 反三角函数 ====================
328
+ def asin(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
329
+ """反正弦函数"""
330
+ if isinstance(x, Decimal) or prec is not None:
331
+ return _decimal_asin(x, prec)
332
+
333
+ if abs(x) > 1:
334
+ raise ValueError("math domain error")
335
+ if x == 1:
336
+ return float(PI) / 2
337
+ elif x == -1:
338
+ return -float(PI) / 2
339
+
340
+ result = float(x)
341
+ term = float(x)
342
+ n = 1
343
+ while True:
344
+ term *= (x ** 2) * (2 * n - 1) ** 2 / (2 * n * (2 * n + 1))
345
+ new_result = result + term
346
+ if abs(new_result - result) < 1e-15:
347
+ break
348
+ result = new_result
349
+ n += 1
350
+ return result
351
+
352
+ def _decimal_asin(x: Decimal, prec: PrecisionType = None) -> Decimal:
353
+ """高精度Decimal版反正弦函数"""
354
+ ctx = Context(prec=prec + 2 if prec else getcontext().prec)
355
+ if abs(x) > 1:
356
+ raise ValueError("math domain error")
357
+ if x == 1:
358
+ return PI / 2
359
+ elif x == -1:
360
+ return -PI / 2
361
+
362
+ result = x
363
+ term = x
364
+ n = 1
365
+ while True:
366
+ term *= (x ** 2) * (Decimal(2 * n - 1) ** 2) / (Decimal(2 * n) * Decimal(2 * n + 1))
367
+ new_result = result + term
368
+ if abs(new_result - result) < Decimal(10) ** (-ctx.prec + 1):
369
+ break
370
+ result = new_result
371
+ n += 1
372
+ return +result
373
+
374
+ def acos(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
375
+ """反余弦函数"""
376
+ if isinstance(x, Decimal) or prec is not None:
377
+ return PI / 2 - _decimal_asin(x, prec)
378
+ return float(PI) / 2 - asin(x)
379
+
380
+ def atan(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
381
+ """反正切函数"""
382
+ if isinstance(x, Decimal) or prec is not None:
383
+ return _decimal_atan(x, prec)
384
+
385
+ if x == 1:
386
+ return float(PI) / 4
387
+ elif x == -1:
388
+ return -float(PI) / 4
389
+ elif abs(x) < 1:
390
+ # 小x用泰勒级数
391
+ result = float(x)
392
+ term = float(x)
393
+ n = 1
394
+ while True:
395
+ term *= -x * x
396
+ new_result = result + term / (2 * n + 1)
397
+ if abs(new_result - result) < 1e-15:
398
+ break
399
+ result = new_result
400
+ n += 1
401
+ return result
402
+ else:
403
+ # 大x用恒等式 atan(x) = π/2 - atan(1/x)
404
+ return float(PI) / 2 - atan(1 / x)
405
+
406
+ def _decimal_atan(x: Decimal, prec: PrecisionType = None) -> Decimal:
407
+ """高精度Decimal版反正切函数"""
408
+ ctx = Context(prec=prec + 2 if prec else getcontext().prec)
409
+ if x == 1:
410
+ return PI / 4
411
+ elif x == -1:
412
+ return -PI / 4
413
+ elif abs(x) < 1:
414
+ result = x
415
+ term = x
416
+ n = 1
417
+ while True:
418
+ term *= -x * x
419
+ new_result = result + term / Decimal(2 * n + 1)
420
+ if abs(new_result - result) < Decimal(10) ** (-ctx.prec + 1):
421
+ break
422
+ result = new_result
423
+ n += 1
424
+ return +result
425
+ else:
426
+ return PI / 2 - _decimal_atan(1 / x, prec)
427
+
428
+ # ==================== 双曲函数 ====================
429
+ def sinh(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
430
+ """双曲正弦函数"""
431
+ if isinstance(x, Decimal) or prec is not None:
432
+ return (_decimal_exp(x, prec) - _decimal_exp(-x, prec)) / 2
433
+ return (exp(x) - exp(-x)) / 2
434
+
435
+ def cosh(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
436
+ """双曲余弦函数"""
437
+ if isinstance(x, Decimal) or prec is not None:
438
+ return (_decimal_exp(x, prec) + _decimal_exp(-x, prec)) / 2
439
+ return (exp(x) + exp(-x)) / 2
440
+
441
+ def tanh(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
442
+ """双曲正切函数"""
443
+ if isinstance(x, Decimal) or prec is not None:
444
+ return sinh(x, prec) / cosh(x, prec)
445
+ return sinh(x) / cosh(x)
446
+
447
+ def coth(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
448
+ """双曲余切函数"""
449
+ if isinstance(x, Decimal) or prec is not None:
450
+ return cosh(x, prec) / sinh(x, prec)
451
+ return cosh(x) / sinh(x)
452
+
453
+ # ==================== 反双曲函数 ====================
454
+ def asinh(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
455
+ """反双曲正弦函数"""
456
+ if isinstance(x, Decimal) or prec is not None:
457
+ return _decimal_ln(x + _decimal_sqrt(x * x + 1, prec), prec)
458
+ return ln(x + sqrt(x * x + 1))
459
+
460
+ def acosh(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
461
+ """反双曲余弦函数"""
462
+ if isinstance(x, Decimal) or prec is not None:
463
+ if x < 1:
464
+ raise ValueError("math domain error")
465
+ return _decimal_ln(x + _decimal_sqrt(x * x - 1, prec), prec)
466
+
467
+ if x < 1:
468
+ raise ValueError("math domain error")
469
+ return ln(x + sqrt(x * x - 1))
470
+
471
+ def atanh(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
472
+ """反双曲正切函数"""
473
+ if isinstance(x, Decimal) or prec is not None:
474
+ if abs(x) >= 1:
475
+ raise ValueError("math domain error")
476
+ return _decimal_ln((1 + x) / (1 - x), prec) / 2
477
+
478
+ if abs(x) >= 1:
479
+ raise ValueError("math domain error")
480
+ return ln((1 + x) / (1 - x)) / 2
481
+
482
+ # ==================== 取整函数 ====================
483
+ def floor(x: AnyNum) -> int:
484
+ """向下取整"""
485
+ if isinstance(x, Decimal):
486
+ return int(x.to_integral_value(rounding='ROUND_FLOOR'))
487
+ return int(x) if x >= 0 or x == int(x) else int(x) - 1
488
+
489
+ def ceil(x: AnyNum) -> int:
490
+ """向上取整"""
491
+ if isinstance(x, Decimal):
492
+ return int(x.to_integral_value(rounding='ROUND_CEILING'))
493
+ return int(x) if x <= 0 or x == int(x) else int(x) + 1
494
+
495
+ def trunc(x: AnyNum) -> int:
496
+ """截断取整"""
497
+ if isinstance(x, Decimal):
498
+ return int(x.to_integral_value(rounding='ROUND_DOWN'))
499
+ return int(x)
500
+
501
+ def round(x: AnyNum, ndigits: int = 0) -> AnyNum:
502
+ """四舍五入"""
503
+ if isinstance(x, Decimal):
504
+ return x.quantize(Decimal(10) ** -ndigits)
505
+ return type(x)(int(x * 10**ndigits + 0.5) / 10**ndigits)
506
+
507
+ # ==================== 特殊函数 ====================
508
+ def factorial(n: int) -> int:
509
+ """阶乘函数"""
510
+ if n < 0:
511
+ raise ValueError("math domain error")
512
+ if n < 2:
513
+ return 1
514
+
515
+ # 分治法优化
516
+ def _product(a, b):
517
+ if a == b:
518
+ return a
519
+ mid = (a + b) // 2
520
+ return _product(a, mid) * _product(mid + 1, b)
521
+
522
+ return _product(1, n)
523
+
524
+ def gamma(x: AnyNum, prec: PrecisionType = None) -> AnyNum:
525
+ """伽马函数(Lanczos近似)"""
526
+ if isinstance(x, Decimal) or prec is not None:
527
+ return _decimal_gamma(x, prec)
528
+
529
+ if x <= 0 and x == int(x):
530
+ raise ValueError("math domain error")
531
+
532
+ # Lanczos近似参数
533
+ g = 7
534
+ p = [
535
+ 0.99999999999980993,
536
+ 676.5203681218851,
537
+ -1259.1392167224028,
538
+ 771.32342877765313,
539
+ -176.61502916214059,
540
+ 12.507343278686905,
541
+ -0.13857109526572012,
542
+ 9.9843695780195716e-6,
543
+ 1.5056327351493116e-7
544
+ ]
545
+
546
+ def _gamma(z):
547
+ if z < 0.5:
548
+ return PI / (sin(PI * z) * _gamma(1 - z))
549
+ z -= 1
550
+ x = p[0]
551
+ for i in range(1, len(p)):
552
+ x += p[i] / (z + i)
553
+ t = z + g + 0.5
554
+ return sqrt(2 * PI) * t ** (z + 0.5) * exp(-t) * x
555
+
556
+ return _gamma(x)
557
+
558
+ def _decimal_gamma(x: Decimal, prec: PrecisionType = None) -> Decimal:
559
+ """高精度Decimal版伽马函数"""
560
+ ctx = Context(prec=prec + 2 if prec else getcontext().prec)
561
+ if x <= 0 and x == int(x):
562
+ raise ValueError("math domain error")
563
+
564
+ g = Decimal(7)
565
+ p = [
566
+ Decimal('0.99999999999980993'),
567
+ Decimal('676.5203681218851'),
568
+ Decimal('-1259.1392167224028'),
569
+ Decimal('771.32342877765313'),
570
+ Decimal('-176.61502916214059'),
571
+ Decimal('12.507343278686905'),
572
+ Decimal('-0.13857109526572012'),
573
+ Decimal('9.9843695780195716e-6'),
574
+ Decimal('1.5056327351493116e-7')
575
+ ]
576
+
577
+ def _gamma(z):
578
+ if z < Decimal('0.5'):
579
+ return PI / (_decimal_sin(PI * z, prec) * _gamma(Decimal(1) - z))
580
+ z -= Decimal(1)
581
+ x = p[0]
582
+ for i in range(1, len(p)):
583
+ x += p[i] / (z + Decimal(i))
584
+ t = z + g + Decimal('0.5')
585
+ return _decimal_sqrt(2 * PI, prec) * t ** (z + Decimal('0.5')) * _decimal_exp(-t, prec) * x
586
+
587
+ return +_gamma(x)
588
+
589
+ # ==================== 测试代码 ====================
590
+ if __name__ == "__main__":
591
+ # 验证基础函数
592
+ assert abs(sqrt(2) - 1.414213562) < 1e-6
593
+ assert abs(exp(1) - float(E)) < 1e-6
594
+ assert abs(ln(float(E))) - 1 < 1e-6
595
+
596
+ # 三角函数验证
597
+ assert abs(sin(PI/2) - 1) < 1e-10
598
+ assert abs(cos(PI) + 1) < 1e-10
599
+ assert abs(tan(PI/4) - 1) < 1e-10
600
+
601
+ # 反三角函数验证
602
+ assert abs(asin(0.5) - 0.523598775) < 1e-6
603
+ assert abs(acos(0.5) - 1.047197551) < 1e-6
604
+ assert abs(atan(1) - PI/4) < 1e-10
605
+
606
+ # 双曲函数验证
607
+ assert abs(sinh(0)) < 1e-10
608
+ assert abs(cosh(0) - 1) < 1e-10
609
+ assert abs(tanh(1) - 0.761594155) < 1e-6
610
+
611
+ # 特殊函数验证
612
+ assert factorial(5) == 120
613
+ assert abs(gamma(0.5) - sqrt(PI)) < 1e-6
614
+
615
+ # 高精度测试
616
+ MathConfig.set_precision(50)
617
+ assert str(exp(Decimal(1)))[:52] == "2.71828182845904523536028747135266249775724709369995"
618
+ assert str(ln(Decimal(10)))[:52] == "2.30258509299404568401799145468436420760110148862877"
619
+
620
+ print("所有测试通过!")
@@ -0,0 +1,24 @@
1
+ """
2
+ ### memoize_utils.py - 高级记忆化装饰器工具集
3
+
4
+ #### 提供功能强大的缓存装饰器
5
+ """
6
+
7
+ import functools
8
+
9
+ def memorize(func):
10
+ """
11
+ 功能强大的缓存装饰器。
12
+ """
13
+ cache = {}
14
+
15
+ @functools.wraps(func)
16
+ def wrapper(*args, **kwargs):
17
+ key = str(args) + str(kwargs)
18
+
19
+ if key not in cache:
20
+ cache[key] = func(*args, **kwargs)
21
+
22
+ return cache[key]
23
+
24
+ return wrapper