Search code examples
pythondata-structuresdivide-by-zero

How to rectify code from zero division error:


I am writing a program to find the cube root of a number. I am getting a division by zero error. I have changed all values to float but still getting the error.

Here is the code.

def cube_root(num):
    import random
    g = random.randint(1,num+1)
    new_g = float(num/(g*g))
    check_ifclose(g,new_g,num)

def check_ifclose(g,new_g,num):
    from math import isclose
    if isclose(g, new_g, abs_tol=0.0000001):
        print("The cube root of ",num,"is ",float(new_g))
    else:
        g = float(new_g)
        new_g = float(num/(g*g))
        check_ifclose(g,new_g,num) 

This is the error that I am getting

ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-53-7ad3ad630bd7> in <module>
----> 1 cube_root(16)

<ipython-input-52-46121e93a109> in cube_root(num)
      3     g = random.randint(1,num+1)
      4     new_g = float(num/(g*g))
----> 5     check_ifclose(g,new_g,num)
      6 
      7 def check_ifclose(g,new_g,num):

<ipython-input-52-46121e93a109> in check_ifclose(g, new_g, num)
     12         g = float(new_g)
     13         new_g = float(num/(g*g))
---> 14         check_ifclose(g,new_g,num)

ZeroDivisionError: float division by zero

Solution

  • Why don't you print the values during each iteration? You'll see what happens, you can then try to debug it and re-think your solution

    Just do:

    def cube_root(num):
        import random
        g = random.randint(1,num+1)
        new_g = float(num/(g*g))
        print("g", g, "new_g", new_g, "num", num)
        check_ifclose(g,new_g,num)
    
    def check_ifclose(g,new_g,num):
        from math import isclose
        print("g", g, "new_g", new_g, "num", num)
        if isclose(g, new_g, abs_tol=0.0000001):
            print("The cube root of ",num,"is ",float(new_g))
        else:
            g = float(new_g)
            new_g = float(num/(g*g))
            check_ifclose(g,new_g,num) 
    

    Then for cube_root(16) you'll get the output:

    >>> cube_root(16)
    g 2 new_g 4.0 num 16
    g 2 new_g 4.0 num 16
    g 4.0 new_g 1.0 num 16
    g 1.0 new_g 16.0 num 16
    g 16.0 new_g 0.0625 num 16
    g 0.0625 new_g 4096.0 num 16
    g 4096.0 new_g 9.5367431640625e-07 num 16
    g 9.5367431640625e-07 new_g 17592186044416.0 num 16
    g 17592186044416.0 new_g 5.169878828456423e-26 num 16
    g 5.169878828456423e-26 new_g 5.986310706507379e+51 num 16
    g 5.986310706507379e+51 new_g 4.464794497196387e-103 num 16
    g 4.464794497196387e-103 new_g 8.02633041618099e+205 num 16
    g 8.02633041618099e+205 new_g 0.0 num 16
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 6, in cube_root
      File "<stdin>", line 9, in check_ifclose
      File "<stdin>", line 9, in check_ifclose
      File "<stdin>", line 9, in check_ifclose
      [Previous line repeated 8 more times]
      File "<stdin>", line 8, in check_ifclose
    ZeroDivisionError: float division by zero
    

    As you can see, it's like Razmik said about the small numbers.

    But why?

    Because your solution is flawed. Are you sure you should calculate new_g like that? If you look here, it goes haywire - very small, then very big, then again small... Why don't you try e.g. setting new_g as average of old and current new to balance it?


    EDIT: Decided to check my last suggestion, it works fine now.

    def cube_root(num):
        import random
        g = random.randint(1,num+1)
        new_g = float(num/(g*g))
        print("g", g, "new_g", new_g, "num", num)
        check_ifclose(g,new_g,num)
    
    def check_ifclose(g,new_g,num):
        from math import isclose
        print("g", g, "new_g", new_g, "num", num)
        if isclose(g, new_g, abs_tol=0.0000001):
            print("The cube root of ",num,"is ",float(new_g))
        else:
            g = float(new_g)
            new_g = (g+float(num/(g*g)))/2
            check_ifclose(g,new_g,num) 
    
    >>> cube_root(16)
    g 3 new_g 1.7777777777777777 num 16
    g 3 new_g 1.7777777777777777 num 16
    g 1.7777777777777777 new_g 3.420138888888889 num 16
    g 3.420138888888889 new_g 2.3939850310351836 num 16
    g 2.3939850310351836 new_g 2.592869433541053 num 16
    g 2.592869433541053 new_g 2.4863846555355664 num 16
    g 2.4863846555355664 new_g 2.537249169224923 num 16
    g 2.537249169224923 new_g 2.51131729000868 num 16
    g 2.51131729000868 new_g 2.524147960725603 num 16
    g 2.524147960725603 new_g 2.517700180896523 num 16
    g 2.517700180896523 new_g 2.52091579334918 num 16
    g 2.52091579334918 new_g 2.519305938864469 num 16
    g 2.519305938864469 new_g 2.520110351423893 num 16
    g 2.520110351423893 new_g 2.51970801680198 num 16
    g 2.51970801680198 new_g 2.5199091519863974 num 16
    g 2.5199091519863974 new_g 2.5198085763676823 num 16
    g 2.5198085763676823 new_g 2.519858862169772 num 16
    g 2.519858862169772 new_g 2.519833718766991 num 16
    g 2.519833718766991 new_g 2.5198462903429375 num 16
    g 2.5198462903429375 new_g 2.519840004523604 num 16
    g 2.519840004523604 new_g 2.519843147425431 num 16
    g 2.519843147425431 new_g 2.519841575972557 num 16
    g 2.519841575972557 new_g 2.519842361698504 num 16
    g 2.519842361698504 new_g 2.519841968835408 num 16
    g 2.519841968835408 new_g 2.5198421652669256 num 16
    g 2.5198421652669256 new_g 2.519842067051159 num 16
    The cube root of  16 is  2.519842067051159