Python: Getting Around Division By Zero
Solution 1:
You are using a np function, so I can safely guess that you are working on a numpy array? Then the most efficient way to do this is to use the where function instead of a for loop
myarray= np.random.randint(10,size=10)
result = np.where(myarray>0, np.log(myarray), 0)
otherwise you can simply use the log function and then patch the hole:
myarray= np.random.randint(10,size=10)
result= np.log(myarray)
result[result==-np.inf]=0
The np.log function return correctly -inf when used on a value of 0, so are you sure that you want to return a 0? if somewhere you have to revert to the original value, you are going to experience some problem, changing zeros into ones...
Solution 2:
Since the log
for x=0
is minus infinite, I'd simply check if the input value is zero and return whatever you want there:
def safe_ln(x):
if x <=0:
return0return math.log(x)
EDIT: small edit: you should check for all values smaller than or equal to 0.
EDIT 2: np.log
is of course a function to calculate on a numpy array, for single values you should use math.log
. This is how the above function looks with numpy:
defsafe_ln(x, minval=0.0000000001):
return np.log(x.clip(min=minval))
Solution 3:
You can do this.
defsafe_ln(x):
try:
l = np.log(x)
except ZeroDivisionError:
l = 0return l
Solution 4:
The answer given by Enrico is nice, but both solutions result in a warning:
RuntimeWarning: divide by zero encountered in log
As an alternative, we can still use the where
function but only execute the main computation where it is appropriate:
# alternative implementation -- a bit more typing but avoids warnings.
loc = np.where(myarray>0)
result2 = np.zeros_like(myarray, dtype=float)
result2[loc] =np.log(myarray[loc])
# answer from Enrico...
myarray= np.random.randint(10,size=10)
result= np.where(myarray>0, np.log(myarray), 0)
# check it is giving right solution:
print(np.allclose(result, result2))
My use case was for division, but the principle is clearly the same:
x = np.random.randint(10, size=10)
divisor = np.ones(10,)
divisor[3] = 0 # make one divisor invalid
y = np.zeros_like(divisor, dtype=float)
loc = np.where(divisor>0) # (or !=0 if your data could have -ve values)
y[loc] = x[loc] / divisor[loc]
Solution 5:
use exception handling:
In [27]: def safe_ln(x):
try:
return math.log(x)
except ValueError: # np.log(x) might raise some other error though
returnfloat("-inf")
....:
In [28]: safe_ln(0)
Out[28]: -inf
In [29]: safe_ln(1)
Out[29]: 0.0In [30]: safe_ln(-100)
Out[30]: -inf
Post a Comment for "Python: Getting Around Division By Zero"