How to divide by 0 in python

CSDN blog divide by 0 problem >This blog is used to record how to deal with the problem of dividing by 0 in python. > Problems encountered: in the process of writing matrix operation and machine learning, we will encounter the problem of matrix division. The previous processing method is to check each element one by one before division, but this will lead to the inability to make use of numpy's parallel computing ability, and finally lead to a significant decline in computing speed.

This website provides good discussion and guidance https://www.codenong.com/26248654/

Here are three ways to divide by 0, in my humble opinion:

  • The first method is more common and general (this general refers to changing to other languages or breaking away from numpy. This idea also feels OK)
  • The second method is the best treatment method. NaN and inF are treated respectively
  • The third method is the most concise processing method. It's good to use it when you have a clear understanding of the wrong situation.

There are two kinds of errors caused by dividing by 0

import numpy as np
# Calculated divisor A, and divisor B
arrayA = np.arange(9).reshape(3,3)
arrayA[0,2]=0
arrayA[2,0]=-2
arrayB = np.array([[1,4,0],
                    [5,0,6],
                    [0,7,2]])
arrayC = arrayA / arrayB
print("arrayA:\n", arrayA)
print("arrayB:\n", arrayB)
print("*****************")
print("arrayA / arrayB\n",arrayC)
arrayA:
 [[ 0  1  0]
 [ 3  4  5]
 [-2  7  8]]
arrayB:
 [[1 4 0]
 [5 0 6]
 [0 7 2]]
*****************
arrayA / arrayB
 [[0.         0.25              nan]
 [0.6               inf 0.83333333]
 [      -inf 1.         4.        ]]

D:\Anaconda\lib\site-packages\ipykernel_launcher.py:8: RuntimeWarning: divide by zero encountered in true_divide
  
D:\Anaconda\lib\site-packages\ipykernel_launcher.py:8: RuntimeWarning: invalid value encountered in true_divide

First, we show that there are two types of errors in the division calculation: 0 / 0 and 1 / 0

  • For the type of 0 / 0, the result is Nan
  • For 1 / 0 type, the result is inf (note - inf)

Idea 1: divide and rule

This method mainly extracts the position of zero element and non-zero element, then calculates the non-zero element, and directly sets the agreed value to the zero element.
However, this method does not operate the two error types divided by 0 separately. If they need to be separated, they need to be further subdivided into three steps:

  1. Non zero element operation for both A and B
  2. Operate on elements where A is non-zero and B is zero
  3. Operate on the fact that A is A zero element and B is also A zero element
myOwnValue = 0 # Set the divisor to 0 and assign a value to it
arrayC = np.zeros(arrayA.shape)
idxNonZeros = np.where(arrayB!=0) # A 2x7 matrix is obtained, which corresponds to the positions of 7 non-zero elements respectively
idxZeros = np.where(arrayB==0)  # Get a 2x2 matrix corresponding to the positions of two zero elements respectively

# Division operates in two steps, first with non-zero elements and then with zero elements
# division in two steps: first with nonzero cells, and then zero cells
arrayC[idxNonZeros] = arrayA[idxNonZeros] / arrayB[idxNonZeros]
arrayC[idxZeros] = myOwnValue # If the Convention is 0, this step is unnecessary, but if the Convention is not 0, such as a maximum value, it is necessary

print("*****************")
print("arrayA / arrayB\n",arrayC)
*****************
arrayA / arrayB
 [[0.         0.25       0.        ]
 [0.6        0.         0.83333333]
 [0.         1.         4.        ]]

Train of thought 2: first calculate and then solve (design warning processing)

The errstate in the first line is the context manager that operates on the handling of floating-point errors

Context manager for floating-point error handling

Conveniently record the error types that can be written in it:

  • Division error of divide 0
  • Invalid invalid floating point number error
  • over floating point overflow
  • Under floating point number down overflow (under flow)
with np.errstate(divide='ignore', invalid='ignore'):
    arrayC = arrayA / arrayB
    # Refer to the error handling methods
#     arrayC[arrayC == np.inf] = 0  # The error of inf will be corrected, and - inf will not be corrected
    arrayC[~ np.isfinite(arrayC)] = 0 # Correct - inf, inf, NaN and set it to 0
#     arrayC = np.nan_to_num(arrayC)  # The errors of - inf, inf and Nan are corrected. The result is set to 0 and inf is set to a large number,
                                      # But the returned is a floating-point number, not True_division
    
print("*****************")
print("arrayA / arrayB\n",arrayC)
*****************
arrayA / arrayB
 [[0.         0.25       0.        ]
 [0.6        0.         0.83333333]
 [0.         1.         4.        ]]

Idea 3: call the division function of numpy

In fact, numpy has already helped you consider the division problem, so it provides a matrix division function, numpy divide()
However, this method can only deal with the problem that the two division errors are 0 and inf cannot be recognized, but it is the most concise.

If the output is out and the dtype type is not specified as a floating-point number, an error will occur (assigning a floating-point number to an integer will lose precision)
If out is not specified here, the same result will appear, but it is uncertain whether the default initial value inside the function is 0

arrayC = np.divide(arrayA, arrayB, out=np.zeros_like(arrayA, dtype=np.float64), where=arrayB!=0)
print("*****************")
print("arrayA / arrayB\n",arrayC)
*****************
arrayA / arrayB
 [[0.         0.25       0.        ]
 [0.6        0.         0.83333333]
 [0.         1.         4.        ]]

Tags: Python

Posted by netpants on Wed, 04 May 2022 01:16:37 +0300