-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathv1_utils.py
53 lines (43 loc) · 1.7 KB
/
v1_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
import math
def userAccurate(number: int | float) -> str:
"""
Displays a number in a human-readable and accurate way
Tries to use scale symbols to represent thousands, millions, and etc.
Uses scale symbols up to 'T' (trillion).
Tries not to round for accurate representation.
However if a fraction is too long, it will still be rounded.
A fraction's leading zeros are ignored for accuracy.
Reference:
https://en.wikipedia.org/wiki/Long_and_short_scales
"""
SCALE_NAMES = ['', 'k', 'M', 'G', 'T']
SCALE_BASES = [1, 1e3, 1e6, 1e9, 1e12]
FRACTION_PRECISION = 3
LENGTH_THRESHOLD = 4
scale_name = ''
scaled_number = number
for scale, base in zip(reversed(SCALE_NAMES), reversed(SCALE_BASES)):
res_div = number / base
if res_div < 1:
continue
scale_name = scale
scaled_number = res_div
break
if type(scaled_number) is float:
if scaled_number.is_integer():
scaled_number = int(scaled_number)
formatted = f'{scaled_number:,}{scale_name}'
# if the scaled number is too long,
# a) if it is an integer:
# falls back to simply formatting with thousands separators
# b) if it is a float: round it
if len(str(scaled_number)) > LENGTH_THRESHOLD and scale_name != 'T':
if isinstance(number, int) or (isinstance(number, float) and number.is_integer()):
return f'{number:,}'
elif abs(number) >= 1:
return f'{round(number, FRACTION_PRECISION):,}'
else:
exponent = int(math.log(abs(number), 10))
rounded = round(number, -exponent + FRACTION_PRECISION)
return str(rounded)
return formatted