Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I write this equation in Python?

Cardano Triplets

I really don't know how to write this correctly. This is how I tried:

def is_cardano_triplet(a, b, c):
    f = lambda x: x ** 1. / 2
    g = lambda x: x ** 1. / 3
    return g(a + b*f(c)) + g(a - b*f(c)) == 1

print is_cardano_triplet(2,1,5) # I should get True

I should get True for 2, 1, 5, but I'm not. What's wrong with my function?

like image 504
Deneb Avatar asked Apr 19 '16 19:04

Deneb


2 Answers

Doing a few calculations, I found out that:

lolz

and therefore:

lolzz

Now, due to floating point arithmetic being imprecise on binary-based systems for known reasons, the first formula is pretty hard to compute precisely. However, the second one is much easier to compute without floating point precision errors since that it doesn't involve irrational functions and a, b and c are integers.

Here's the smart solution:

def is_cardano_triplet(a, b, c):
    return (a + 1)**2 * (8*a - 1) - 27*b**2*c == 0

>>> is_cardano_triplet(2, 1, 5)
True
like image 116
Marco Bonelli Avatar answered Oct 31 '22 00:10

Marco Bonelli


The power operator (**) has a higher priority than the division one (/). So you need to set parentheses:

f = lambda x: x ** (1./3)

Still, floating point operations are not exact, so you have to compare with some small uncertainty:

def is_cardano_triplet(a, b, c):
    f = lambda x: x ** (1. / 2)
    g = lambda x: x ** (1. / 3)
    return abs(g(a + b*f(c)) + g(a - b*f(c)) - 1) < 1e-10

Now you get the problem, that negative numbers are only allowed for roots of odd numbers, but floating points aren't exact, so you have to handle negative numbers by hand:

def is_cardano_triplet(a, b, c):
    f = lambda x: x ** (1. / 2)
    g = lambda x: (-1 if x<0 else 1) * abs(x) ** (1. / 3)
    return abs(g(a + b*f(c)) + g(a - b*f(c)) - 1) < 1e-10

Now

print is_cardano_triplet(2,1,5)

results in True.

like image 25
Daniel Avatar answered Oct 31 '22 00:10

Daniel