Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
3.7k views
in Technique[技术] by (71.8m points)

How to divide in python without using //?

This is the code that I already have and it just need to be tweaked. I think the formulas may not all be correct. I only need the quotient.

def divide(x, y):
    if x == 0 or y == 0: 
        return 0
    if x < 0 and y < 0:
        return divide(0 - x, 0 - y)
    if x < 0 or y < 0:
        return 0 - 1 - divide(0 - x, y)
    else:
       return divide_helper(x, y, 0)  
def divide_helper(x, y, temp):
    if y >= x:
        return x
    else:
        return divide_helper(x - y, y, temp + 1)

divide(-5,-2) should give me 2

divide(13,3) should give me 4


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Code Review:

Scenario #1: x negative, y positive; abs(x) > abs(y)

Let's review your code with example x = -8 and y = 5. The code will go into this section:

def divide(x, y): # x = -8 , y = 5
    if x < 0 or y < 0: #satisfies x < 0 as -8 < 0
        return 0 - 1 - divide(0 - x, y) # -1 -divide(8,5)

This will send the call back to divide function with values 8,5. It will skip all if statements and go into the below given else statement with values 8, 5.

def divide(x, y):
    else:
       return divide_helper(x, y, 0)

Let's assume divide_helper function gives you the correct result, you will receive a positive (+) result 1 because 8 can be divided by 5 once (1)

Taking this result back to the called function, you will get:

def divide(x, y): # x = -8 , y = 5
    if x < 0 or y < 0:
        return 0 - 1 - divide(0 - x, y) # return -1 -1 as [result of divide(8,5) = 1]

You are now going to return -2 instead of -1 which is incorrect.

Fix#1:

if x < 0 or y < 0:
    return -divide(-x, y) #remove (0 - 1)

However, it does not address the sign issue

Scenario #2: x positive, y negative; abs(x) > abs(y)

Let's look at the code again with another example of x = 8 and y = -5. This time the code will go into section:

def divide(x, y): # x = 8 , y = -5
    if x < 0 or y < 0: #satisfies y < 0 as -5 < 0
        return 0 - 1 - divide(0 - x, y) # -1 -divide(-8,-5)

This goes through the same process and ends up with the same fix we discussed above. Again, this does not address the sign issue

Now let's review the second function that calculates the quotient:

def divide_helper(x, y, temp):
    if y >= x:
        return x
    else:
        return divide_helper(x - y, y, temp + 1)

Let's consider the example of x = 5, y = 8. The code satisfies the if statement and returns x which is 5. That's incorrect. It should return 0 as 5 cannot be divided by 8. Therefore this function is incorrect for values where x < y.

Similarly, if x = 5 and y = 5, it will return 5. That is also incorrect. It should have returned 1 as x divides by y only once (1).

Now let's look at x = 8, y = 5. In this case, it goes into the else statement calling divide_helper function with x = 3, y = 5. (x = x-y = 8-5 = 3). This time it returns 3. This is again incorrect.

Looking at your code, I think you wanted to return temp instead of x.

Fix#2:

def divide_helper(x, y, temp):
    if y > x: #changed to only check if y > x
              #When y=x, you need to increment temp by 1
        return temp
    elif x == y: #check explicitly for x==y and increment temp by 1
        return temp+1
    else:
        return divide_helper(x - y, y, temp + 1)

These two fixes should address your divide problem. However, this does not address the sign issue. If x is + and y is - or if x is - and y is +, it will still return + instead of -. The updated and fixed code is as shown below:

def divide(x, y):
    if x == 0 or y == 0: 
        return 0
    if x < 0 and y < 0:
        return divide(-x, -y)
    if x < 0 or y < 0:
        return divide(-x, y)
    else:
       return divide_helper(x, y, 0)
       
def divide_helper(x, y, temp):
    if y > x:
        return temp
    elif x == y:
        return temp+1
    else:
        return divide_helper(x - y, y, temp + 1)

While the above code does solve the quotient problem (excluding the sign issue), the code is calling the function too many times. In some cases, the call could have been avoided. Below is an alternate approach to solve this. See if it helps.

Alternate Approach:

In the below approach, the code does not call the function too many times. It also addresses the sign problem.

Here's the full implementation of the code. There are a few scenarios to address. You don't need 2 functions to calculate the results. Instead you can use a loop to iterate and increment the counter. Also, it is important to keep tab of the sign for each of the input parameters. This will decide the resultant (quotient) sign. As you know (+ and +) = +; (+ and -) = -; (- and +) = -; and (- and -) = +.

We also know that if numerator is 0 or numerator is less than denominator, the answer will be 0. If the denominator is 0, I am forcing a result of 0 (instead of infinity). For all other cases, we need to compute the value by iterating through the loop.

The full code with comments for each line is as follows:

def div_check(x, y):
    #if either x or y is 0, return 0
    if 0 in (x,y): return 0
    
    #set the sign to positive (+)
    s = 1
    #if x & y are both negative numbers, result sign will be positive (+)
    if (x < 0) and (y < 0): s = 1
    #If x is negative and y is positive or the other way around, result sign will be negative (-)
    if ((x < 0) and (y > 0)) or ((y < 0) and (x > 0)): s = -1
    #convert x and y to absolute value so we can compute division
    x,y = abs(x), abs(y)
    #if x is less than y, then result is 0
    if x < y : return 0
    #initialize result r to zero
    r = 0
    #iterate through the loop each time x is greater than or equal to y while incrementing counter r by 1
    while x >= y:
        x-=y
        r+=1
    #multiply the sign s to result r to give the final result 
    return s*r
    
print ('(2,5)    ',div_check(2,5))
print ('(-2,-5)  ',div_check(-2,-5))
print ('(-2,5)   ',div_check(-2,5))

print ('(-5,2)   ',div_check(-5,2))
print ('(5,-2)   ',div_check(5,-2))
print ('(-5,-2)  ',div_check(-5,-2))

print ('(0,5)    ',div_check(0,5))
print ('(2,0)    ',div_check(2,0))

print ('(13,3)   ',div_check(13,3))
print ('(-25,5)  ',div_check(-25,5))

print ('(-39,-13)',div_check(-39,-13))

print ('(24,-7)  ',div_check(24,-7))
print ('(3,14)   ',div_check(3,14))
print ('(14,3)   ',div_check(14,3))

#This also works for floats. The quotient will be integer
print ('(14.5,3.5)',div_check(14.5,3.5))
print ('(25.6,4.2)',div_check(25.6,-4.2))

The output of this will be:

(2,5)     0
(-2,-5)   0
(-2,5)    0
(-5,2)    -2
(5,-2)    -2
(-5,-2)   2
(0,5)     0
(2,0)     0
(13,3)    4
(-25,5)   -5
(-39,-13) 3
(24,-7)   -3
(3,14)    0
(14,3)    4
(14.5,3.5) 4
(25.6,4.2) -6

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...