Quadratic formula returning wrong results

Hi all,
I’m trying to get “x” from the Quadratic formula where:

  • a = 1 (so I don’t include it in the formula)
  • b = Sin(α) (Mathf.Sin requires the angle to be in radiants)
  • c = -2 * area

The code to calculate it is this:

float alphaRad = Mathf.Deg2Rad * alpha; //alpha is a positive float from 0 to 90
float x = (-Mathf.Sin(alphaRad) + Mathf.Sqrt(Mathf.Pow(Mathf.Sin(alphaRad), 2) - 4 * (- 2 * _area))) / 2;

Here is a table with the results for “X” that should be, and the ones I get from the code:

Is there something I’m missing? Thanks!

Why write this all as one line?

Break it up, do one step at a time, and see where it differs between your “calculation” and the code.

If you have more than one or two dots (.) in a single statement, you’re just being mean to yourself.

How to break down hairy lines of code:

http://plbm.com/?p=248

Break it up, practice social distancing in your code, one thing per line please.

2 Likes

I took your code verbatim into this .NET fiddle. I copied your “area” values and go through all of your alpha angles. I get the expected results from your “calculator”. So I have no idea what could be wrong on your side. Either your “area” is not what you think it is, or the provided code is not your actual code.

Anyways, I’m with Kurt that you should break down your calculation into smaller steps. Pow is unnecessarily complicated. When you put your “b” value into an actual variable “b” you can simply calculate b*b.

1 Like

using System;

Use Microsoft system Math Sin and feed it the full value because the accuracy you want exceeds the capability of float by +2 digits. Float(8) Double(11). Double is indeed just enough and some.

In other words/ the significant digits of a float are in quantity 6 - 7, but the significant digits of a double are in quantity 15 - 16

Try again with the compact code in double.

1 Like

Thank you all for your replies!

Following AnimalMan 's suggestion, I switched to System and changed my floats to doubles, and it now returns the expected values. I will also follow your advice and separate the code to make it more readable.

Cheers!

That’s not possible. First of all Unity is using the System.Math methods under the hood, just casted to floats. As AnimalMan said a float has about 6-7 significant decimal digits. However the error you said you are seeing is in the most significant digit which is not possible. The type double would only increase the number of significant digits, however the results would be the same in the most significant digits. I’ve run your exact code and I get the expected results. I’m not even sure how you could even end up at anything near your wrong results. Your issue had to be somewhere else. Maybe you had not saved your latest changes?

Don’t get me wrong, we are happy that you solved your issue, however the threads in this forum should help others with similar issues as well. While switching to a higher precision variable type can fix certain issues, it can’t in your specific case. At least not with the values you have provided. You gave use clear angle and area values and a concrete piece of code. I was not able to reproduce your wrong results. I got the correct results (just with less digits). So your conclusion is misleading.

2 Likes

I understand, the last thing I want is this post being misleading. In my last comment, I forgot to mention I also changed the “area” to double, so it could be that the previous float area value also contributed to it. The results I had before were wrong but consistent, it makes sense to me that those wrong decimals lead up to a bigger difference. I’m confident yesterday I closed Unity after saving, posted this, went to sleep and I didn’t open Unity until today after reading the replies.

1 Like

Thing is changing the area to double also wouldn’t radically change the values like this.

Example:

    private void Start()
    {
        var sb = new StringBuilder();

        var arr = new[]
        {
            (5, 0.02112716),
            (10, 0.04121076),
            (15, 0.07670123),
            (20, 0.1153387),
            (25, 0.1618201),
            (30, 0.2244108),
            (35, 0.3140703),
            (40, 0.3879602),
            (45, 0.5),
            (50, 0.6103955)
        };

        foreach(var tup in arr)
        {
            sb.AppendLine(string.Format("{0} | {1} | {2} | {3}", tup.Item1, tup.Item2, DoSingle(tup.Item1, (float)tup.Item2), DoDouble(tup.Item1, tup.Item2)));
        }

        Debug.Log(sb.ToString());

    }

    private float DoSingle(float alpha, float area)
    {
        float alphaRad = Mathf.Deg2Rad * alpha; //alpha is a positive float from 0 to 90
        float x = (-Mathf.Sin(alphaRad) + Mathf.Sqrt(Mathf.Pow(Mathf.Sin(alphaRad), 2) - 4 * (-2 * area))) / 2;
        return x;
    }

    private double DoDouble(double alpha, double area)
    {
        double alphaRad = Mathf.Deg2Rad * alpha; //alpha is a positive float from 0 to 90
        double x = (-System.Math.Sin(alphaRad) + System.Math.Sqrt(System.Math.Pow(System.Math.Sin(alphaRad), 2) - 4 * (-2 * area))) / 2;
        return x;
    }

This results in:

5  | 0.02112716 | 0.1665491 | 0.166549116387459
10 | 0.04121076 | 0.2131091 | 0.213109141545409
15 | 0.07670123 | 0.283082  | 0.283082035036858
20 | 0.1153387  | 0.3388152 | 0.338815237115605
25 | 0.1618201  | 0.3955613 | 0.395561324829143
30 | 0.2244108  | 0.4650676 | 0.465067550398975
35 | 0.3140703  | 0.556057  | 0.55605701331107
40 | 0.3879602  | 0.6162705 | 0.616270516939687
45 | 0.5        | 0.7071067 | 0.707106782620556
50 | 0.6103955  | 0.786378  | 0.786378063041708

Note that the float and double results (3rd and 4th columns) are effectively the same value. Only difference being the number of sig values to the right.

But in the end, the most significant values towards the left are equal.

0.1665491 ~ 0.16654911…

Your values are vastly different relative speaking. They’re not even consistently different. They start out 1.17 times larger, shoot up to 1.68 times different by the 5th entry, then start dropping down in scale to 1.58 by the end. A float->double bug would be more linear. This curved result in difference implies some error with a curve… curves like sines and squareroots.

I don’t know what caused your original issue, but I’m just clarifying for future people, that no… changing from float to double is NOT what fixed the problem.

I’m with @Bunny83 in that you probably were running a different version of your code. Potentially from the result of not saving (you say you closed it and reopened the next day. You could have saved it when you closed it. But it wasn’t saved before you closed it and ran your first test which was your results in OP).

1 Like