-1

How do I write a python def function that can take the cube roots of fractions and return the answer as a fraction as a coefficient with a cube root in the numerator only? I am new to coding, so I apologize if my question sounds vague. I am trying to write a program that can solve any cubic equation and return that answer in its exact form. Currently, I have a program that can do this, but it only gives the roots as a decimal.

For example, I want the answers of:

      This ∛10 / ∛56 = ∛490/14       Not ∛10 / ∛56 = 0.56312394

      This ∛1 / ∛27 = 1/3       Not ∛1 / ∛27 = 0.333333333

      This ∛48 / ∛9 = 6∛18/9       Not ∛48 / ∛9 = 1.74716092

Basically, I just need -cubic_root(c) to be return as a fraction instead of a decimal

def cubic_root(x): 
        '''Compute cubic root of a number while maintaining its sign'''
        if x >= 0:
            return x**third #x**third means x^3
        else:
            return -(-x)**third

    if f == g == h == 0:
        x1 = -cubic_root(c) # I need this in fraction form

This is the entire code

'''
Cubic Equation Calculator (Exact Form)
By Patrick Thomas
'''

import time
import math
import fractions
goAgain = True

time.sleep(0.5)
print('')
print('Cubic Equation Calculator (Exact Form)')
time.sleep(0.5)
print('A Patman Inc. Program')

#While Loop---------------------------------------------------------------------
while goAgain == True:
    time.sleep(0.5)
    print('--------------------------')
    print('ax³ + bx² + cx + d = 0')
    print('--------------------------')
    
    a = int(input('a = '))
    
    b = int(input('b = '))
    
    c = int(input('c = '))
    
    d = int(input('d = '))
    
    print('')
    
#Math---------------------------------------------------------------------------
    a0 = b/a
    b0 = c/a
    c0 = d/a
    #a0 Fraction--------------------------------------------------------------------
    def a0(b,a):
        if int(a) == 0:
            return int(b)
        return a0(int(a), int(b) % int(a))
    a0_GCD = a0(b,a)
    b_Simp = int(b) / a0_GCD
    a_Simp = int(a) / a0_GCD
    a0_frac = fractions.Fraction(int(b_Simp),int(a_Simp))
    print('a0 = {}'.format(a0_frac)) #remove when finished
    
    #b0 Fraction--------------------------------------------------------------------
    def b0(c,a):
        if int(a) == 0:
            return int(c)
        return b0(int(a), int(c) % int(a))
    b0_GCD = b0(c,a)
    c_Simp = int(c) / b0_GCD
    a_Simp = int(a) / b0_GCD
    b0_frac = fractions.Fraction(int(c_Simp),int(a_Simp))
    print('b0 = {}'.format(b0_frac)) #remove when finished
    
    #c0 Fraction--------------------------------------------------------------------
    def c0(d,a):
        if int(a) == 0:
            return int(d)
        return b0(int(a), int(d) % int(a))
    c0_GCD = c0(d,a)
    d_Simp = int(d) / b0_GCD
    a_Simp = int(a) / b0_GCD
    c0_frac = fractions.Fraction(int(d_Simp),int(a_Simp))
    print('c0 = {}'.format(c0_frac)) #remove when finished
    
    a0 = b/a
    b0 = c/a
    c0 = d/a
    
    a = a0
    b = b0
    c = c0
    
    # Some repeating constants and variables
    third = 1./3. #Cube root
    a13 = a*third #a is divided by 3
    a13_num = int(b_Simp) * 1 
    a13_den = int(a_Simp) * 3
    a13_frac = fractions.Fraction(a13_num,a13_den)
    print('') #remove when finished
    print('a13 (decimal) = {}'.format(a13)) #remove when finished
    print('a13 (fraction) = {}'.format(a13_frac)) #remove when finished
    
    a2 = a13*a13 #quotient of a*third times quotient of a*third
    a2_num = a13_num * a13_num
    a2_den = a13_den * a13_den
    a2_frac = fractions.Fraction(int(a2_num),int(a2_den))
    print('') #remove when finished
    print('a2 (decimal) = {}'.format(a2)) #remove when finished
    print('a2 (fraction) = {}'.format(a2_frac)) #remove when finished
    sqr3 = math.sqrt(3)
    
    # Additional intermediate variables
    
    #f--------------------------------------------------------------------------
    f = third * b - a2
    thirdb_num = 1 * int(c_Simp) 
    thirdb_den = 3 * int(a_Simp)
    thirdb = fractions.Fraction(thirdb_num,thirdb_den)
    f_frac = thirdb - a2_frac
    
    print('') #remove when finished
    print('f (decimal) = {}'.format(f)) #remove when finished
    print('f (fraction) = {}'.format(f_frac)) #remove when finished
    
    #g--------------------------------------------------------------------------
    g = a13 * (2*a2 - b) + c
    paren = 2*a2 - b
    two_a2_num = 2 * a2_num
    two_a2_den = 1 * a2_den
    two_a2_frac = fractions.Fraction(int(two_a2_num),int(two_a2_den))
    parenthesis = two_a2_frac - b0_frac
    g_frac = a13_frac * parenthesis + c0_frac
    
    print('') #remove when finished
    print('g (decimal) = {}'.format(g)) #remove when finished
    print('g (fraction) = {}'.format(g_frac)) #remove when finished
    
    #h--------------------------------------------------------------------------
    h = 0.25*g*g + f*f*f
    one_forth = fractions.Fraction(int(1),int(4))
    h_frac = one_forth * g_frac * g_frac + f_frac * f_frac * f_frac
    print('') #remove when finished
    print('h (decimal) = {}'.format(h)) #remove when finished
    print('h (fraction) = {}'.format(h_frac)) #remove when finished
    
    #cubic_root(x)--------------------------------------------------------------
    def cubic_root(x): 
        '''Compute cubic root of a number while maintaining its sign'''
        if x >= 0:
            return x**third #x**third means x^3
        else:
            return -(-x)**third

    if f == g == h == 0:
        x1 = -cubic_root(c) # I need this in fraction form
        print('x₁ = {:.5f}'.format(x1))
        print('x₂ = {:.5f}'.format(x1))
        print('x₃ = {:.5f}'.format(x1))

    elif h <= 0:
        j = math.sqrt(-f)
        k = math.acos(-0.5*g / (j*j*j))
        m = math.cos(third*k)
        n = sqr3 * math.sin(third*k)
        x1 = 2*j*m - a13
        x2 = -j * (m + n) - a13
        x3 = -j * (m - n) - a13
        print('x₁ = {:.5f}'.format(x1))
        print('x₂ = {:.5f}'.format(x2))
        print('x₃ = {:.5f}'.format(x3))

    else:
        sqrt_h = math.sqrt(h)
        S = cubic_root(-0.5*g + sqrt_h)
        U = cubic_root(-0.5*g - sqrt_h)
        S_plus_U = S + U
        S_minus_U = S - U
        x1 = S_plus_U - a13
        x2 = -0.5*S_plus_U - a13 + S_minus_U*sqr3*0.5j
        x3 = -0.5*S_plus_U - a13 - S_minus_U*sqr3*0.5j
        
    #x1 Section-----------------------------------------------------------------
        print('') #remove when finished
        print('x₁ = {:.5f}'.format(float(x1)))
        
    #x2 Section-----------------------------------------------------------------
    x2_str = str(x2)
    
    if '+' in x2_str:
        x2_part1, x2_part2 = x2_str.split('+')
        x2_part1 = x2_part1.replace('(','')
        x2_part2 = x2_part2.replace('j)','')
        x2_part1_num = float(x2_part1)
        x2_part2_num = float(x2_part2)
        if float(x2_part2_num) == 0:
            print('x₂ = {:.5f}'.format(x2_part1_num))
        else:
            print('x₂ = {:.5f} + {:.5f}i'.format(x2_part1_num,x2_part2_num))
        
    elif '-' in x2_str:
        if '(-' in x2_str:
            x2_str = x2_str.replace('(-','')
            x2_part1, x2_part2 = x2_str.split('-')
            x2_part1 = x2_part1.replace('','-',1)
            x2_part1 = x2_part1.replace('(','')
            x2_part2 = x2_part2.replace('j)','')
            x2_part1_num = float(x2_part1)
            x2_part2_num = float(x2_part2)
            if float(x2_part2_num) == 0:
                print('x₂ = {:.5f}'.format(x2_part1_num))
            else:
                print('x₂ = {:.5f} - {:.5f}i'.format(x2_part1_num,x2_part2_num))
        else:
            x2_part1, x2_part2 = x2_str.split('-')
            x2_part1 = x2_part1.replace('(','')
            x2_part2 = x2_part2.replace('j)','')
            x2_part1_num = float(x2_part1)
            x2_part2_num = float(x2_part2)
            if float(x2_part2_num) == 0:
                 print('x₂ = {:.5f}'.format(x2_part1_num))
            else:
                print('x₂ = {:.5f} - {:.5f}i'.format(x2_part1_num,x2_part2_num))
            
    #x3 Section-----------------------------------------------------------------
    x3_str = str(x3)
    
    if '+' in x3_str:
        x3_part1, x3_part2 = x3_str.split('+')
        x3_part1 = x3_part1.replace('(','')
        x3_part2 = x3_part2.replace('j)','')
        x3_part1_num = float(x3_part1)
        x3_part2_num = float(x3_part2)
        if float(x3_part2_num) == 0:
            print('x₃ = {:.5f}'.format(x3_part1_num))
        else:
            print('x₃ = {:.5f} + {:.5f}i'.format(x3_part1_num,x3_part2_num))
        
    elif '-' in x3_str:
        if '(-' in x3_str:
            x3_str = x3_str.replace('(-','')
            x3_part1, x3_part2 = x3_str.split('-')
            x3_part1 = x3_part1.replace('','-',1)
            x3_part1 = x3_part1.replace('(','')
            x3_part2 = x3_part2.replace('j)','')
            x3_part1_num = float(x3_part1)
            x3_part2_num = float(x3_part2)
            if float(x3_part2_num) == 0:
                print('x₃ = {:.5f}'.format(x3_part1_num))
            else:
                print('x₃ = {:.5f} - {:.5f}i'.format(x3_part1_num,x3_part2_num))
        else:
            x3_part1, x3_part2 = x3_str.split('-')
            x3_part1 = x3_part1.replace('(','')
            x3_part2 = x3_part2.replace('j)','')
            x3_part1_num = float(x3_part1)
            x3_part2_num = float(x3_part2)
            if float(x3_part2_num) == 0:
                print('x₃ = {:.5f}'.format(x3_part1_num))
            else:
                print('x₃ = {:.5f} - {:.5f}i'.format(x3_part1_num,x3_part2_num))
        
Patman1O1
  • 5
  • 4
  • Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. – Community Jun 19 '22 at 16:34

2 Answers2

0

You really need to be more clear about what you want to achieve but here is an answer based on what I could understand from your question:

You need to look into the Fractions module. Here is script that does what you explained in your second example.

from fractions import Fraction

def cuberoot(number: float) -> float:
    if number < 0:
        number = abs(number)
        cube_root = number**(1/3)*(-1)
    else:
        cube_root = number**(1/3)
    return cube_root

def cube_root_fraction(initial_fraction: Fraction) -> Fraction:
    numerator = int(cuberoot(initial_fraction.numerator))
    denominator =  int(cuberoot(initial_fraction.denominator))
    return Fraction(numerator, denominator)
 
initial_fraction = Fraction(1, 27)
result = cube_root_fraction(initial_fraction)
print(result)

Input:

Fraction(1, 27)

Output:

1/3
Geom
  • 1,491
  • 1
  • 10
  • 23
0

To get rid of the cube root in the denominator, we can multiply both numerator and denominator with the square of that cube root. For example:

      ∛48 / ∛9 = ∛48∛9² / ∛9∛9² = ∛(48⋅9²) / 9

Then a factor should be extracted from the cube root that is a cube. For that purpose we could find all factors and then identify those that have a power of 3 or more. The powers of 3 can be extracted out of the cube root. We can either code this ourselves, or make use of sympy.ntheory.factor_.core with t=3, which extracts the cube-free factor, so that we can derive what the cube factor is.

In the example, we can write the fraction as:

      ∛(48⋅9²) / 9 = ∛(6³18) / 9 = 6∛18 / 9

The core function will give us the 18 from 48⋅9², and from the remaining factor 6³ (which always is a perfect cube) we can derive 6.

And then finally we can divide both the coefficient part of the numerator and the denominator by their greatest common divisor (which Fraction will do for us), and so we get:

      6∛18 / 9 = 2∛18 / 3

from fractions import Fraction
from sympy.ntheory.factor_ import core  # for getting the cube free factor
from sympy import integer_nthroot  # for applying the integer cube-root

def rationalize(root3numerator, root3denominator):
    root3numerator *= root3denominator * root3denominator
    cubefree = core(root3numerator, t=3)
    cube,_ = integer_nthroot(root3numerator // cubefree, 3)
    return (Fraction(cube, root3denominator), cubefree)

# Helper function for formatting output
def format(fraction, root3):
    strdenominator = "" if fraction.denominator == 1 else f"/{fraction.denominator}"
    strroot3 = "" if root3 == 1 else f"∛{root3}"
    strcoefficient = "" if fraction.numerator == 1 and strroot3 else str(fraction.numerator)
    return f"{(fraction, root3)}: {strcoefficient}{strroot3}{strdenominator}"

# Example runs
for num, denom in [(10, 56), (1, 27), (48, 9), (20, 2)]:
    print((num, denom), "=>", format(*rationalize(num, denom)))
trincot
  • 317,000
  • 35
  • 244
  • 286
  • This works great! However, when I try to do ³⎷16 / ³⎷3, I get (144,3) when I should get 2 ³⎷18 / 3. Is there a way to modify this to make it return the correct answer? – Patman1O1 Jun 21 '22 at 04:12
  • Sure, but then the output should consist of three numbers. Would be good if your question had such specification. – trincot Jun 21 '22 at 05:14
  • OK, I edited your question for you. I updated my answer, which now returns 3 numbers: two in the form of a Fraction (numerator, denominator) and one number that needs the cube-root applied to it. – trincot Jun 21 '22 at 08:56
  • thank you for your help. I'm new to coding so I'm sorry if I'm not very specific when it comes to questions. I am currently majoring in computer science after taking a coding class last fall and I fell in love with it. Right now I trying to get my gen eds out of the way so I can take more coding and software classes. – Patman1O1 Jun 21 '22 at 17:13
  • Basically, I am trying to write a program that can solve any cubic equation and return that answer in its exact form. Every cubic equation calculator that I have seen only returns the answer in decimal notation. Personally, I hate decimals because they are often irrational and I want the exact answer. Plus I am trying to challenge myself with something sophisticated. I wrote a quadratic equation calculator that can return the answer in its exact form and provide the same equation in vertex form, the axis of sym, y-int, and the vertex. – Patman1O1 Jun 21 '22 at 17:20
  • I will provide the quadratic equation calculator, the cubic equation calculator that can only give the answer in decimal notation, and the cubic equation calculator, which I am working on currently that can give the answer in its exact form. – Patman1O1 Jun 21 '22 at 17:23
  • My quadratic equation calculator is too long to post on Stack Overflow so I have copied the code to a Google Doc and have made the link public in case you are interested. https://docs.google.com/document/d/1mYa9dBjdbVUAMSoNBK_9MiCkFi3631BTwL5qPX5IADU/edit?usp=sharing – Patman1O1 Jun 21 '22 at 17:39