How do I write this equation in Python?
Solution 1
Doing a few calculations, I found out that:
and therefore:
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
Solution 2
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
.
Related videos on Youtube
Deneb
Updated on July 25, 2022Comments
-
Deneb almost 2 years
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
for2, 1, 5
, but I'm not. What's wrong with my function?-
Jeremy about 8 yearsTake a look at Is floating point math broken?
-
user2357112 about 8 yearsYou'll need to reformulate your equation to work purely in terms of integers, or perhaps bring in a sufficiently powerful symbolic math library. (Also,
x ** 1. / 2
is(x ** 1.) / 2
, notx ** (1. / 2)
.)
-
-
Tadhg McDonald-Jensen about 8 yearswhile this is part of it, the function still returns False because of floating point rounding, see Is floating point math broken?.
-
Drew Delano about 8 years
print is_cardano_triplet(2,1,5)
gives:ValueError: negative number cannot be raised to a fractional power
for me. -
user2357112 about 8 yearsComparing with a tolerance will just produce different wrong results. You'll get false positives for inputs that aren't Cardano triplets.
-
user2357112 about 8 yearsOf course, to solve the Project Euler problem, generating triplets and testing whether they're Cardano triplets would still be unworkably inefficient. You might try iterating over possible values of
(a + 1) / 3
(asa
must be congruent to 2 mod 3) and considering factors of(a + 1) / 3
and square factors of(8*a - 1) / 3
to generate validb
values, from which the correspondingc
immediately follows.