Quadratic Equation Roots in C, C++, Java, and Python
Algorithm, discriminant logic, and working code to find all roots of a quadratic equation in C, C++, Java, and Python, covering real, equal, and complex root cases.
A quadratic equation has exactly two roots, and the discriminant b² - 4ac determines their nature before a single root is computed.
That single number controls three distinct execution paths in the program: two distinct real roots when positive, two equal real roots when zero, and two complex conjugate roots when negative. Every correct implementation of this problem branches on the discriminant sign first, then computes.
The original FACE Prep article on this topic contained a worked example with incorrect root values (the legacy arithmetic mixed coefficient signs mid-calculation). The numbers below are re-derived from first principles.
The Three Root Cases
For the general quadratic equation ax² + bx + c = 0, the discriminant is:
D = b² - 4ac
The sign of D determines both the number and nature of the roots.
Case 1: D > 0 (Two Distinct Real Roots)
- Formula: r1 = (-b + sqrt(D)) / (2a), r2 = (-b - sqrt(D)) / (2a)
- Worked example: a = 1, b = -5, c = 6
- D = (-5)² - 4(1)(6) = 25 - 24 = 1
- r1 = (5 + 1) / 2 = 3.00
- r2 = (5 - 1) / 2 = 2.00
- Verification: (x - 3)(x - 2) = x² - 5x + 6 ✓
Case 2: D = 0 (Two Equal Real Roots)
- Formula: r1 = r2 = -b / (2a)
- Worked example: a = 1, b = -4, c = 4
- D = (-4)² - 4(1)(4) = 16 - 16 = 0
- r1 = r2 = 4 / 2 = 2.00
- Verification: (x - 2)² = x² - 4x + 4 ✓
Case 3: D < 0 (Two Complex Conjugate Roots)
- Formula: r1 = p + qi, r2 = p - qi, where p = -b / (2a) and q = sqrt(-D) / (2a)
- Worked example: a = 1, b = 2, c = 5
- D = (2)² - 4(1)(5) = 4 - 20 = -16
- p = -2 / 2 = -1.0
- q = sqrt(16) / 2 = 4 / 2 = 2.0
- r1 = -1 + 2i, r2 = -1 - 2i
- Verification: (x + 1 - 2i)(x + 1 + 2i) = (x+1)² + 4 = x² + 2x + 5 ✓
A note on the D = 0 check in code: comparing a floating-point variable exactly to zero using == 0 can miss cases where D is a very small non-zero value due to floating-point rounding. For placement-test problems, the inputs are typically integers and the discriminant is an integer too, so exact equality is safe. For production-grade code, compare D against a small epsilon.
Algorithm
The algorithm translates directly from the three cases above:
- Step 1: Read coefficients a, b, c.
- Step 2: Compute D = b * b - 4 * a * c.
- Step 3: If D > 0, compute and print two distinct real roots using sqrt(D).
- Step 4: Else if D == 0, compute and print one repeated real root as -b / (2a).
- Step 5: Else (D < 0), compute real_part = -b / (2a), imag_part = sqrt(-D) / (2a), and print r1 = real_part + imag_part * i, r2 = real_part - imag_part * i.
- Step 6: End.
The order of checks matters. Testing D == 0 before D < 0 is cleaner than testing D > 0, D == 0, then the default, but either order produces identical output on valid input.
C and C++ Implementation
Both C and C++ use sqrt() from the cmath header to compute square roots. The key difference: C uses printf and scanf for I/O, while C++ uses cin and cout. The branching logic is identical.
C Code
#include <stdio.h>
#include <math.h>
int main() {
double a, b, c, D, r1, r2, real_part, imag_part;
printf("Enter coefficients a, b, c: ");
scanf("%lf %lf %lf", &a, &b, &c);
D = b * b - 4 * a * c;
if (D > 0) {
r1 = (-b + sqrt(D)) / (2 * a);
r2 = (-b - sqrt(D)) / (2 * a);
printf("Two distinct real roots:\n");
printf("r1 = %.4lf\n", r1);
printf("r2 = %.4lf\n", r2);
} else if (D == 0) {
r1 = -b / (2 * a);
printf("Two equal real roots:\n");
printf("r1 = r2 = %.4lf\n", r1);
} else {
real_part = -b / (2 * a);
imag_part = sqrt(-D) / (2 * a);
printf("Two complex conjugate roots:\n");
printf("r1 = %.4lf + %.4lfi\n", real_part, imag_part);
printf("r2 = %.4lf - %.4lfi\n", real_part, imag_part);
}
return 0;
}
Sample output for a=1, b=-5, c=6 (Case 1):
Two distinct real roots:
r1 = 3.0000
r2 = 2.0000
Sample output for a=1, b=2, c=5 (Case 3):
Two complex conjugate roots:
r1 = -1.0000 + 2.0000i
r2 = -1.0000 - 2.0000i
C++ Code
#include <iostream>
#include <cmath>
using namespace std;
int main() {
double a, b, c, D;
cout << "Enter coefficients a, b, c: ";
cin >> a >> b >> c;
D = b * b - 4 * a * c;
if (D > 0) {
double r1 = (-b + sqrt(D)) / (2 * a);
double r2 = (-b - sqrt(D)) / (2 * a);
cout << "Two distinct real roots:" << endl;
cout << "r1 = " << r1 << endl;
cout << "r2 = " << r2 << endl;
} else if (D == 0) {
double r1 = -b / (2 * a);
cout << "Two equal real roots:" << endl;
cout << "r1 = r2 = " << r1 << endl;
} else {
double real_part = -b / (2 * a);
double imag_part = sqrt(-D) / (2 * a);
cout << "Two complex conjugate roots:" << endl;
cout << "r1 = " << real_part << " + " << imag_part << "i" << endl;
cout << "r2 = " << real_part << " - " << imag_part << "i" << endl;
}
return 0;
}
The C++ version is structurally identical to the C version. For placements at service-tier companies like TCS and Infosys, either language is acceptable; the interviewer cares about the branching logic and the correct use of the square-root function, not the I/O syntax.
Java and Python Implementation
Java and Python each have their own approach to the complex-root case. Java requires manual imaginary-component arithmetic; Python can route all three cases through a single cmath.sqrt() call.
For a similar multi-language comparison on another common placement problem, the palindrome check article covers two-pointer and reverse-and-compare approaches in C, C++, Java, and Python with the same structure.
Java Code
import java.util.Scanner;
public class QuadraticRoots {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter coefficients a, b, c: ");
double a = sc.nextDouble();
double b = sc.nextDouble();
double c = sc.nextDouble();
double D = b * b - 4 * a * c;
if (D > 0) {
double r1 = (-b + Math.sqrt(D)) / (2 * a);
double r2 = (-b - Math.sqrt(D)) / (2 * a);
System.out.println("Two distinct real roots:");
System.out.printf("r1 = %.4f%n", r1);
System.out.printf("r2 = %.4f%n", r2);
} else if (D == 0) {
double r1 = -b / (2 * a);
System.out.println("Two equal real roots:");
System.out.printf("r1 = r2 = %.4f%n", r1);
} else {
double realPart = -b / (2 * a);
double imagPart = Math.sqrt(-D) / (2 * a);
System.out.println("Two complex conjugate roots:");
System.out.printf("r1 = %.4f + %.4fi%n", realPart, imagPart);
System.out.printf("r2 = %.4f - %.4fi%n", realPart, imagPart);
}
}
}
Java’s Math.sqrt() is the direct equivalent of C’s sqrt(). It does not accept negative arguments safely, so the negative-discriminant branch passes -D (made positive) to Math.sqrt(). java.lang.Math has no method that returns a complex number directly.
Python Code
Python’s cmath module extends the standard math module to cover complex arithmetic. cmath.sqrt() accepts a negative real argument and returns a complex number, which means all three discriminant cases can route through the same sqrt call.
import cmath
a = float(input("Enter a: "))
b = float(input("Enter b: "))
c = float(input("Enter c: "))
D = b**2 - 4*a*c
sqrt_D = cmath.sqrt(D)
r1 = (-b + sqrt_D) / (2 * a)
r2 = (-b - sqrt_D) / (2 * a)
if D > 0:
print("Two distinct real roots:")
print(f"r1 = {r1.real:.4f}")
print(f"r2 = {r2.real:.4f}")
elif D == 0:
print("Two equal real roots:")
print(f"r1 = r2 = {r1.real:.4f}")
else:
print("Two complex conjugate roots:")
print(f"r1 = {r1.real:.4f} + {r1.imag:.4f}i")
print(f"r2 = {r2.real:.4f} - {abs(r2.imag):.4f}i")
The Python version calls cmath.sqrt(D) before the if-else block. When D is positive, the imaginary part of sqrt_D is 0.0. When D is negative, it carries the imaginary component. The branching only controls how the output is formatted, not which computation path runs.
This is the most concise of the four implementations. Python’s Tier-2 college placement tests (AMCAT Automata in particular) increasingly accept Python submissions, so this version is directly usable in those contexts.
Time Complexity and Interview Follow-ups
The quadratic root finder runs in O(1) time and O(1) space. It performs a fixed number of arithmetic operations regardless of the magnitude of a, b, and c. No loop, no recursion, no data structure.
That said, interviewers at mid-size IT companies and product firms often follow up with extensions:
- Edge case: a = 0. When a is zero, the equation is linear (bx + c = 0), not quadratic. The program above divides by 2a, so a = 0 triggers a division-by-zero error. A defensive implementation checks for this and either rejects the input or solves the linear case separately.
- Edge case: a = 0 and b = 0. If both a and b are zero, the equation reduces to c = 0. If c is also zero, every real number is a solution (trivially true equation). If c is non-zero, there are no solutions.
- Output precision. Some placement tests specify the number of decimal places. The
%.4lfformat in C/C++ and:.4fin Python give four decimal places. Java’s%.4fdoes the same. - Finding the sum and product of roots. By Vieta’s formulae, r1 + r2 = -b/a and r1 * r2 = c/a. These identities hold without computing sqrt and are a common verification shortcut in interviews.
Three skills intersect in this problem: using a math library correctly, writing multi-branch conditional logic, and formatting floating-point output. The data structures interview questions guide covers the next layer: arrays, linked lists, and tree traversal, which typically follow this warmup in the same technical round.
Finding the smallest and largest element in an array is a natural companion problem. Both run in O(1) per input, and both expect a complexity justification before the code.
The three-case discriminant logic in this article (compute a value, branch on its sign, produce typed output) is the same conditional-routing pattern Python-based LLM pipelines use to classify model responses. Same structure, different domain. TinkerLLM is ₹299 to experiment with that in Python, the same language as the cmath root finder above.
Primary sources
Frequently asked questions
What does a negative discriminant mean for a quadratic equation?
When the discriminant D = b² - 4ac is less than zero, the quadratic has no real roots. It has two complex conjugate roots of the form p + qi and p - qi, where p = -b / (2a) and q = sqrt(|D|) / (2a). The equation cannot be factored over the real numbers.
How do C and C++ handle complex roots in this program?
The standard sqrt() function is undefined for negative inputs in C and C++. The program checks the discriminant sign first. When D is negative, it computes sqrt(-D) and formats the imaginary component manually, rather than passing a negative value to sqrt().
Can Python's cmath handle all three discriminant cases in one call?
Yes. cmath.sqrt() accepts negative real arguments and returns a complex number. When D is positive, the imaginary part of the result is 0.0. The Python version can call cmath.sqrt(D) for all three cases without a sign check, though explicit branching makes the output formatting cleaner.
What is the time complexity of finding the roots of a quadratic equation?
O(1). The program performs a fixed number of arithmetic operations regardless of the size of the coefficients a, b, and c. No loops, no recursion, and no data structure traversal are involved.
Do AMCAT or CoCuBES placement tests include quadratic equation programs?
Yes. AMCAT Automata and CoCuBES coding rounds include this as a warmup-level problem. It tests whether a candidate handles multiple branches correctly, uses math library functions (sqrt, Math.sqrt, cmath.sqrt) accurately, and formats floating-point output with the right precision.
What is the formula for the roots of a quadratic equation?
For the equation ax² + bx + c = 0, the roots are r1 = (-b + sqrt(D)) / (2a) and r2 = (-b - sqrt(D)) / (2a), where D = b² - 4ac is the discriminant. When D is negative, sqrt(D) is imaginary, so the roots are complex conjugates.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)