-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathnumber_utils.py
98 lines (83 loc) · 2.76 KB
/
number_utils.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import re
import math
from latex2sympy2 import latex2sympy
from math import sqrt, sin, cos, log, pi, factorial, exp, e
E = 2.718
def floatify(num: str):
try:
num = float(num)
if num.is_integer():
return round(num)
else:
return num
except Exception:
return None
def within_eps(pred: float, gt: float):
eps = abs(gt) * 0.04
if pred >= gt - eps and pred <= gt + eps:
return True
else:
return False
def clean_units(pred_str: str):
"""Clean the units in the number."""
def convert_pi_to_number(code_string):
code_string = code_string.replace('\\pi', 'π')
# Replace \pi or π not preceded by a digit or } with 3.14
code_string = re.sub(r'(?<![\d}])\\?π', '3.14', code_string)
# Replace instances where π is preceded by a digit but without a multiplication symbol, e.g., "3π" -> "3*3.14"
code_string = re.sub(r'(\d)(\\?π)', r'\1*3.14', code_string)
# Handle cases where π is within braces or followed by a multiplication symbol
# This replaces "{π}" with "3.14" directly and "3*π" with "3*3.14"
code_string = re.sub(r'\{(\\?π)\}', '3.14', code_string)
code_string = re.sub(r'\*(\\?π)', '*3.14', code_string)
return code_string
pred_str = convert_pi_to_number(pred_str)
pred_str = pred_str.replace('%', '/100')
pred_str = pred_str.replace('$', '')
pred_str = pred_str.replace('¥', '')
pred_str = pred_str.replace('°C', '')
pred_str = pred_str.replace(' C', '')
pred_str = pred_str.replace('°', '')
return pred_str
def number_it(num):
if isinstance(num, (int, float)):
return num
num = clean_units(num)
try:
num = str(latex2sympy(num))
except Exception:
pass
if floatify(num) is not None:
return floatify(num)
else:
try:
num = eval(num)
if isinstance(num, list) or isinstance(num, tuple):
num = num[0]
if floatify(num) is not None:
return floatify(num)
else:
return None
except Exception:
return None
def compare_two_numbers(p, gt):
try:
if math.isnan(p):
return False
if isinstance(gt, int):
return round(p) == gt
else:
return within_eps(pred=p, gt=gt)
except Exception:
return False
def compare_two_list(pred, gt):
if not isinstance(pred, list):
return False
elif len(pred) != len(gt):
return False
elif any([not isinstance(x, (int, float)) for x in pred]):
return False
else:
pred = sorted(pred)
gt = sorted(gt)
return all([compare_two_numbers(p, g) for p, g in zip(pred, gt)])