forked from cool-RR/python_toolbox
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmisc.py
More file actions
155 lines (119 loc) · 4.09 KB
/
misc.py
File metadata and controls
155 lines (119 loc) · 4.09 KB
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# Copyright 2009-2015 Ram Rachum.
# This program is distributed under the MIT license.
from __future__ import division
import numbers
import math
infinity = float('inf')
infinities = (infinity, -infinity)
def cute_floor_div(x, y):
'''
Get `x // y`, i.e. `x` divided by `y` floored down.
This differs from Python's built-in `//` in that it handles infinite
`x`s in a more mathematically correct way: `infinity // 7` would equal
`infinity`. (Python's built-in `divmod` would make it `nan`.)
'''
if ((x in infinities) and (y != 0)) or \
(y in infinities) and (x not in infinities):
return x / y
else:
return x // y
def cute_divmod(x, y):
'''
Get the division and modulo for `x` and `y` as a tuple: `(x // y, x % y)`
This differs from Python's built-in `divmod` in that it handles infinite
`x`s in a more mathematically correct way: `infinity // 7` would equal
`infinity`. (Python's built-in `divmod` would make it `nan`.)
'''
if (x in infinities) and (y != 0):
return (x / y, float('nan'))
elif (y in infinities) and (x not in infinities):
return (
x / y,
x if (get_sign(x) == get_sign(y)) else float('nan')
)
else:
return divmod(x, y)
def get_sign(x):
'''Get the sign of a number.'''
if x > 0:
return 1
if x == 0:
return 0
assert x < 0
return -1
def round_to_int(x, up=False):
'''
Round a number to an `int`.
This is mostly used for floating points. By default, it will round the
number down, unless the `up` argument is set to `True` and then it will
round up.
If you want to round a number to the closest `int`, just use
`int(round(x))`.
'''
rounded_down = int(cute_floor_div(x, 1))
if up:
return int(x) if (isinstance(x, float) and x.is_integer()) \
else rounded_down + 1
else:
return rounded_down
def ceil_div(x, y):
'''Divide `x` by `y`, rounding up if there's a remainder.'''
return cute_floor_div(x, y) + (1 if x % y else 0)
def convert_to_base_in_tuple(number, base):
'''
Convert a number to any base, returning result in tuple.
For example, `convert_to_base_in_tuple(32, base=10)` will be `(3, 2)` while
`convert_to_base_in_tuple(32, base=16)` will be `(2, 0)`.
'''
assert isinstance(number, numbers.Integral)
assert isinstance(base, numbers.Integral)
assert base >= 2
sign_ = get_sign(number)
if sign_ == 0:
return (0,)
elif sign_ == -1:
raise NotImplementedError
work_in_progress = []
while number:
work_in_progress.append(int(number % base))
number //= base
return tuple(reversed(work_in_progress))
def restrict_number_to_range(number, low_cutoff=-infinity,
high_cutoff=infinity):
'''
If `number` is not in the range between cutoffs, return closest cutoff.
If the number is in range, simply return it.
'''
if number < low_cutoff:
return low_cutoff
elif number > high_cutoff:
return high_cutoff
else:
return number
def binomial(big, small):
'''
Get the binomial coefficient (big small).
This is used in combinatorical calculations. More information:
http://en.wikipedia.org/wiki/Binomial_coefficient
'''
if big == small:
return 1
if big < small:
return 0
else:
return (math.factorial(big) // math.factorial(big - small)
// math.factorial(small))
def product(numbers):
'''Get the product of all the numbers in `numbers`.'''
from python_toolbox import misc_tools
return misc_tools.general_product(numbers, start=1)
def is_integer(x):
'''
Is `x` an integer?
Does return `True` for things like 1.0 and `1+0j`.
'''
try:
inted_x = int(x)
except (TypeError, ValueError, OverflowError):
return False
return inted_x == x