I am a new Rust Lang learner and I have been writing a Rust version of the Po-Shen Loh (Mathematician) solution to ALL quadratic equations. The solution is so amazing that I wanted to use it to leverage my skills on Rust.

I am happy to be able to share this with you all and please, make me even happier by letting me know how much better this could have been written if you have the time.

If not, I'd still appreciate if you can just check it on my Repl.it and let me know if you find any bugs! I have tested it with my beginner skills and could not find any although I am sure they are hiding there.

You should run rustfmt on it by doing cargo fmt. Notably this changes the number of spaces per tab and adds spaces where appropriate (such as in the use statement);

You could refactor all of your I/O into a function.

You say if !a.trim().parse::<i32>().is_ok(), this could be if a.trim.parse::<i32>().is_err().

In the case of an invalid input, you need not create a new string, and instead just .clear() it.

In the case of the expects, it would be nice to use ? notation, however that may be tricky.

loops can return values, and your code could be simplified to something like this:

let mut a = String::new();
let a = loop {
stdin().read_line(&mut a)?;
// Side note, you don't need the first if statement, since it already
// doesn't parse an empty string:
// https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=73f906e0fcbd329c50e87d0afa7c4adb
match a.trim().parse::<i32>() {
Ok(x) => break x, //Return x from this loop
Err(_) => println!("There was an error with your input, please check again!"),
}
};

You check parsing against a i32, but then immediately convert it to an f64. It would probably be easier to just parse against an f64. (Although you may not want to do this because this may also allow NaNs to be parse)

You check the sign of things, however f64 has a nice method for that: f64::is_sign_[positive/negative]. However, these deal with +/-0.0 too.

You duplicate code on saying This is the resulting quadratic equation: ..., which could have been placed in front of the if/else.

Don't precede names with _ unless you're going to never use them.

You can use the sign formatter to avoid having to deal with the sign of your numbers.

I'm not familiar with the Po-Shen Loh method for solving quadratic equations, so I can't help you on that end.

I think to parse as i32 and convert to f64 I would do this

let a: f64 = loop {
// ...
match a.trim().parse::<i32>() {
Ok(x) => break x.into(),

or in a function

fn read_number() -> f64 {
loop {
let mut buf = String::new();
stdin()
.read_line(&mut buf)
.expect("Error reading user input");
match buf.trim().parse::<i32>() {
Ok(x) => break x.into(), //Return x from this loop
Err(_) => println!("There was an error with your input, please check again!"),
}
}
}

If parsing as floats is acceptable and you want to avoid NaN you could do

match buf.trim().parse::<f64>() {
Ok(x) if !x.is_nan() => break x, //Return x from this loop
_ => println!("There was an error with your input, please check again!"),
}

I agree with all your other points as well and don't have much else to add beyond this

It's a brilliantly simple and elegant way of teaching how to solve quadratic equations without the drudge of having to derive and then memorize the famous quadratic equation.

I wish all mathematics was taught that way, with an emphasis on understanding the underlying ideas rather than blindly memorizing solutions. It would make maths far more fun and accessible to more people.

This so called "Po-Shen Loh method" is far from a new technique, miraculous or mind opening. It was known thousands of years ago to Babylonians, Greeks, Egyptians, Chinese, Persians, etc... Nowadays it's called completing the square. It's also the standard way used to derive the quadratic formula in school.

There is a bug: a=1, b=0, c=1 returns 1 and -1 as solutions instead of i and -i. I didn't read the code, but 106 lines for a buggy implementation to solve a quadratic equation doesn't seem very optimal...

I recommend something more like this.Three implementations: the first using the classic formula, the second reducing to a monic equation, the third optimizing a bit. This last one is pretty much the same as your method, except it is correct.

Thank you for the method comments Federico, in my opinion, the way solutions are taught make the difference. Po-Shen Loh demonstration was the turn of the key for me.

Also thanks for finding the bug. The intention was really to get such feedback since I am new to Rust and not to demonstrate a fully optimized version of it. I guess some additional 9964 hours of Rust and lots of feedback like these might get me there

Will check the bug you mentions and the links to learn more and get better for the next rounds

I'm very sure Po would never claim that this was a new idea.

Indeed. But there in lies the point.

What Po has observed is that when we are taught maths in school we all go through the derivation of the famous quadratic formula. We then learn that formula by heart and regurgitate it when required. It's even set to a cheerful tune so that we can sing it and that way have it stuck in our minds forever. Most kids never remember how to derive the quadratic formula, even the few percent that understood it in the first place

My experience of a maths education suggests Po is correct in his observation. I suspect many others would agree.

In general Po is about making the concepts of mathematics stick in kids minds. Never mind memorizing ugly formula like the quadratic equation. If you have the concept in your mind then there is no need for that tedious memorization we are all forced into.

Well, I cannot argue with that. I have even seen classmates using the formula to find the roots of quadratic polynomials already factorized. Like, from (x-2)(x+3), expand to x^2 + x - 6, and use the formula to get 2 and -3.

I think the problem here is more with the math and less with Rust. For instance, in your code you cannot deal with complex numbers, which is inevitable when trying to solve quadratic equations (even with real coefficients), unless you want to bail out with an error like "unable to proceed because the discriminant is negative" in some instances, which I don't think is very useful. A better approach would be to embrace the complexity and use a return type that suitably captures the nature of the problem. You don't even need to code complex numbers yourself, as they are already available in libraries.

Looking at your code, I see a bunch of abs() calls here and there. I believe you put them to work around errors in subsequent sqrt() calls. This is wrong. There is no absolute value to be taken in solving the equation, so putting some in the algorithm just to avoid "errors" will lead to incorrect answers (as in the bug I pointed out). I can even tell you that the bug occurred in the first trial I attempted. If I see some code that promises to solve quadratic equations, the first test that I'm going to try is find the square root of -1.

You remind me of one of my class mates decades ago in school. After a few weeks of starting algebra he was still trying to work things out on the basis that "a" is 1, "b" is 2, "c" is 3, etc. Well, he had some logic in his mind

I have been watching Po almost every day for the last month, he did a daily live stream on youtube for high school kids "Ask Math Anything". Answering all kind of fun questions at involving algebra and geometry, pre-calculus level, it was amazing to revisit my school days maths but viewed very differently.

Now, if only I could remember more than 1% of what I learned at graduate level...