0

I want to find the number of intersection points, but my code works only if all a, b, c numbers are equal e.g. if i change a2 to 0, and c2 to 2, it should print 2, but it prints 0. Can you spot the mistake?

import matplotlib.pyplot as plt
import math as m
import numpy as np

a1 = 1
b1 = 1
c1 = 1
a2 = 1
b2 = 1
c2 = 1

x1 = np.arange(-10, 10, 0.1)

y1 = []
y2 = []
sum = 0
for x in x1:
    y1.append(a1 * m.pow(x, 2) + b1 * x + c1)
    y2.append(a2 * m.pow(x, 2) + b2 * x + c2)
    if (a1 - a2) * m.pow(x, 2) + (b1 - b2) * x + c1 - c2 == 0:
        sum += 1
print(sum)
plt.plot(x1, y1)
plt.plot(x1, y2)
plt.grid(True)
plt.show()
  • Please add an example where the code doesn't give the expected answer. – JohanC Nov 16 '19 at 12:58
  • 2
    One problem is in your test `... == 0` which for floats almost never is exactly equal. Another problem is that you go in steps of 0.1 for x, which means you might never hit the point where the two equations are equal. And if you would make your test too wide (`fabs(...) < some epsilon`) you might count the same root twice. – JohanC Nov 16 '19 at 13:03
  • See also https://stackoverflow.com/questions/588004/is-floating-point-math-broken – JohanC Nov 16 '19 at 13:04
  • It is definitely a floating point issue (though of course there could be other bugs in addition to that). One solution would be to use the fractions module for the computations since you do seem to be using rational parameters. – John Coleman Nov 16 '19 at 13:11
  • @JohnColeman This `if Fraction((a1 - a2) * m.pow(x, 2)) + Fraction((b1 - b2) * x) + (c1 - c2) == 0:` doesn't work for me. Maybe i'm doing something wrong –  Nov 16 '19 at 15:19
  • If you are using `fractions`, don't use `math.pow`. Just use `x**2` (making sure that `x` is a `Fraction` object). The point of using `fractions` is to *avoid* floating point math, which is exactly what `math.pow()` does. – John Coleman Nov 16 '19 at 15:31
  • Ok, i've changed `math.pow` to `x**2`, but it still doesn't work –  Nov 16 '19 at 15:50
  • Is `x1` an iterable of `Fractions` objects? If you go the fractions route, there shouldn't be any floats hiding in your code. In any event -- why do you expect the parabolas to intersect at numbers like `4.1`? If you are looking for rational intersection points, then fractions is relevant. If you are looking for intersection points, why not just use the quadratic formula? – John Coleman Nov 16 '19 at 16:30
  • 1
    Your code (as is) can be fixed of floating point errors involving `==` by using fractions, but the logic error of just hoping you sample at an intersection point can't be fixed in that way. Despite my recommending it (and it is a good module to be aware of), I think that `fractions` won't really help you after all. – John Coleman Nov 16 '19 at 16:37

1 Answers1

1

By simply doing small steps for x it is improbable to step on the exact solution. If you'ld use fractions, be careful that x also needs to be a fraction, otherwise you always encounter precision problems. Using fractions, you can get exact equality provided you step on the correct x. Without fractions, you have a high chance that even with the correct x there still is a small difference due to limited precision.

One way to find exact solutions, is to use symbolic mathematics to solve the system of equations. For example using Python's sympy.

Here is an example:

from sympy import Eq, Symbol, plot
from sympy.solvers import solve

x = Symbol('x', real=True)
a1 = 2
b1 = 3
c1 = 4
a2 = -5
b2 = 1
c2 = 12
equation = Eq(a1*x*x+b1*x+c1, a2*x*x+b2*x+c2)
sol = solve (equation, x)

print("Given equation:", equation)
print("Solutions found:", sol)
print("Solutions as float:", [s.evalf() for s in sol])
print("The number of real solutions:", len(sol))

Which outputs:

Given equation: Eq(2*x**2 + 3*x + 4, -5*x**2 + x + 12)
Solutions found: [-1/7 + sqrt(57)/7, -sqrt(57)/7 - 1/7]
Solutions as float: [0.935690633610107, -1.22140491932439]
The number of real solutions: 2
JohanC
  • 71,591
  • 8
  • 33
  • 66
  • 1
    `fractions` is only relevant when the roots are rational, which of course isn't the case in general, even when the coefficients are integers. Your solution makes sense . +1 – John Coleman Nov 16 '19 at 18:03
  • Indeed. General square roots aren't fractions. – JohanC Nov 16 '19 at 18:39