-1

I want to compare two arrays and if all the values are the same i will do some stuff. I write a function like this to check is there any different value. If so return false.

bool Deneme () 
{
    for (int i = 0; i < correctOnes.Length; i++) {

        if(correctOnes[i] != cubeRotation[i].rotation.eulerAngles) 
        {
            return false;
        }
    }
    return true;
}

When I call the Deneme function it always return false. However, I check the array values in the console they are all same. Any ideas what is going on ?

Checking the console like that

    for (int i = 0; i < correctOnes.Length; i++) {

        Debug.Log ("Corrects: " + correctOnes[i]);  
        Debug.Log ("Cubes: "  + cubeRotation[i].rotation.eulerAngles);  

    }

Console Photo: enter image description here

Backs
  • 24,430
  • 5
  • 58
  • 85
Çağatay Kaya
  • 417
  • 1
  • 6
  • 19
  • If they are equal, why aren't you using Array.Equals()? – Camilo Terevinto Dec 26 '15 at 01:08
  • @cFrozenDeath: For two reasons; because it's an array of values that is compared to properties in an array of objects, and because `Array.Equals` compares the references not the array values. – Guffa Dec 26 '15 at 01:11
  • What is the type of the values that you compare? – Guffa Dec 26 '15 at 01:13
  • Vector3 I both try float but result is same – Çağatay Kaya Dec 26 '15 at 01:14
  • Are you sure you're comparing the right values in the debugger? Your code seems correct at a glance - put a breakpoint on the `return false;` statement and check the value of `i`. Is it index 0? Is it at the end of the array? – xxbbcc Dec 26 '15 at 01:20
  • Yes i am sure indexs are correct. I edit the question show the console message – Çağatay Kaya Dec 26 '15 at 01:24
  • What namespace is Vector3 in? Does it implement IComparable? I would breakpoint and inspect all elements of the arrays manually, or add some Debug.WriteLine(...) to help clarify. – Élie Dec 26 '15 at 01:26
  • 2
    I don't believe you. Post your debug logs. – choz Dec 26 '15 at 01:27
  • hahah @choz you are funny. I do not implement IComparable. I have only one single scripts so no need to put them namespace. – Çağatay Kaya Dec 26 '15 at 01:29
  • If you are using the Vector3 I think you are using, the components will be floats. http://docs.unity3d.com/ScriptReference/Vector3.html Float comparisons are well known for being troublesome. You generally want to include some sort of 'tolerance'. http://stackoverflow.com/questions/3874627/floating-point-comparison-functions-for-c-sharp – Élie Dec 26 '15 at 01:33
  • 4
    You're being backed by floating point? Then there are problems with comparing equals. [If you're doing any sort of calculation on the number, your expected result may not (and often won't) match the calculated result](http://stackoverflow.com/questions/588004/is-floating-point-math-broken). – Clockwork-Muse Dec 26 '15 at 01:34
  • 4
    Quite probably, this is because of a precision error. Printed might look the same but, when compared, they differ by some (very small) value. – xfx Dec 26 '15 at 01:34
  • Convert all the values to int and see the differences. Very helpfull comments. Thak you so much. – Çağatay Kaya Dec 26 '15 at 01:43
  • That's how the logs help, I missed everything :( – choz Dec 26 '15 at 02:26
  • 1
    Unity is best come back. :D @choz – Çağatay Kaya Dec 26 '15 at 02:32

3 Answers3

1

The most likely reason for this is that eulerAngles is double, which means that it should not be compared with operator ==. Two numbers may look the same when printed, but they would compare as non-equal.

The trick here is to compare using Math.Abs(a-b) < 1E-8 method:

if(Math.Abs(correctOnes[i]-cubeRotation[i].rotation.eulerAngles) < 1E-8) {
    ...
}

Above, 1E-8 is a small number that represents the tolerance for comparing doubles for equality.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • Are you sure `Double.Epsilon` is the right constant? That is the smallest positive number that can be represented in a `double`. Correct me if I'm wrong but this check is esentially the same as using `==`. I think some larger (but still small) epsilon should be used, like `1e-8` – Tamas Hegedus Dec 26 '15 at 01:53
  • this doesnt work for me. double.eplision i think something around 4. – Çağatay Kaya Dec 26 '15 at 01:58
  • @ÇağatayKaya I think epsilon is too small for your purposes. Try `1E-8` instead. – Sergey Kalinichenko Dec 26 '15 at 02:06
0

I posted the test scaffolding for completeness, but the linq query at line #35 should get you your pass/fail results.

class Ans34467714
{
    List<double> correctOnes = new List<double>() { 22.7, 22.6, 44.5, 44.5, 44.5};
    List<rotation> cubeRotation = new List<rotation>() { new rotation() { eulerAngles = 22.3 }, new rotation() { eulerAngles = 22.6 }, new rotation() { eulerAngles = 44.5 }, new rotation() { eulerAngles = 44.5 }, new rotation() { eulerAngles = 44.5 } };

    public Ans34467714()
    {

    }

    internal bool Execute(string[] args)
    {
        bool retValue = false;
        if (Deneme())
        {
            Console.WriteLine("Pass");
        }
        else
        {
            Console.WriteLine("Fail");
        }

        return retValue;
    }
    internal bool Deneme()
    {
        return correctOnes.Where((var, index) => cubeRotation[index].eulerAngles == var).Count() == correctOnes.Count;
    }
}
class rotation
{
    public double eulerAngles {get; set;}
    public rotation()
    {

    }

}
Paul
  • 176
  • 3
  • 16
0

You can have a try with

bool Deneme () 
{
    for (int i = 0; i < correctOnes.Length; i++) {

        if (!Mathf.Approximately (correctOnes[i].magnitude, cubeRotation[i].rotation.eulerAngles.magnitude))     
        {
            return false;
        }
    }
    return true;
}
Hamza Hasan
  • 1,368
  • 9
  • 17