Home > Blockchain >  Switch statement skips cases and goes to default
Switch statement skips cases and goes to default

Time:08-24

I have a switch statement that assigns a value to an array of two dimensions depending on the case. The problem is that sometimes the cases are skipped and the default case is called. There seems to be no pattern to the functioning of the switch (sometimes works and sometimes goes to default).

I have tried changing the type of the value that I am giving to the switch from float to string because, in other questions that I saw before, the problem was the data type.

I also checked that the value that I was giving to the switch was one of the cases and I debug.log the "code"(variable of the value that I am giving to my switch) and it is always one of the cases.

I even changed the switch statement to a chain of if-else statements to see if I wrote the switch wrong but that didn't help.

The following code is a function that is generating the "code" that is given to the switch function that goes to default.

private void NodeEnumeration()
{
    //for each node in _mapArray
    for(int i = 0; i < _mapSize; i  )
    {
        for(int e = 0; e < _mapSize; e  )
        {
            //if node value is not 0
            if(_mapArray[i, e] != 0)
            {
                float code = 0f;
                //Left
                if(e != 0)
                {
                    _surroundingNodesPositions[0].x = e - 1;
                    _surroundingNodesPositions[0].y = i;

                    if(_mapArray[(int)_surroundingNodesPositions[0].y, (int)_surroundingNodesPositions[0].x] > 0)
                    {
                        code  = 1f;
                    }
                }
                //Up
                if(i != 0)
                {
                    _surroundingNodesPositions[1].x = e;
                    _surroundingNodesPositions[1].y = i - 1;
                    if(_mapArray[(int)_surroundingNodesPositions[1].y, (int)_surroundingNodesPositions[1].x] > 0)
                    {
                        code  = 0.1f;
                    }
                }
                //Right
                if(e != _mapSize - 1)
                {
                    _surroundingNodesPositions[2].x = e   1;
                    _surroundingNodesPositions[2].y = i;
                    if(_mapArray[(int)_surroundingNodesPositions[2].y, (int)_surroundingNodesPositions[2].x] > 0)
                    {
                        code  = 0.01f;
                    }
                }
                //Down
                if(i != _mapSize - 1)
                {
                    _surroundingNodesPositions[3].x = e;
                    _surroundingNodesPositions[3].y = i   1;
                    if(_mapArray[(int)_surroundingNodesPositions[3].y, (int)_surroundingNodesPositions[3].x] > 0)
                    {
                        code  = 0.001f;
                    }
                }

                AssignValue(i, e, code);//! Here is the problem
            }
        }
    }
}

private void AssignValue(int i, int e, float code)
{
    switch(code)
    {
        case 1.111f:
            _mapArray[i, e] = 1;
        break;

        case 1.110f:
            _mapArray[i, e] = 2;
        break;

        case 1.101f:
            _mapArray[i, e] = 3;
        break;

        case 1.100f:
            _mapArray[i, e] = 4;
        break;

        case 1.011f:
            _mapArray[i, e] = 5;
        break;

        case 1.010f:
            _mapArray[i, e] = 6;
        break;

        case 1.001f:
            _mapArray[i, e] = 7;
        break;

        case 1.000f:
            _mapArray[i, e] = 8;
        break;

        case 0.111f:
            _mapArray[i, e] = 9;
        break;

        case 0.110f:
            _mapArray[i, e] = 10;
        break;

        case 0.101f:
            _mapArray[i, e] = 11;
        break;

        case 0.100f:
            _mapArray[i, e] = 12;
        break;

        case 0.011f:
            _mapArray[i, e] = 13;
        break;

        case 0.010f:
            _mapArray[i, e] = 14;
        break;

        case 0.001f:
            _mapArray[i, e] = 15;
        break;

        case 0.000f:
            _mapArray[i, e] = 16;
        break;

        default:
            Debug.LogError("MapGenerator::NodeEnumeration()::AssignValue() no value can be assigned | code: "   code);
            Debug.Log("height: "   i   " width: "   e);
        break;
    }
}

CodePudding user response:

The problem that you're dealing with is a result of floating point (im)precision. Read through the answer here, as it explains it a lot better that I could do.


TLDR: you can't rely on decimal math to be precise, even simple equations such as 0.1f 0.2f != 0.3f. In most cases, you should just use integer math, or epsilons for judging if two floating point values are equal:

private static float EPSILON = 0.0005f;
public static bool AreApproximatelyEqual(float a, float b)
{
    return Mathf.Abs(a - b) < EPSILON;
}

However, in your case specifically, we can do a LOT better than just using floating point epsilons, or even integer math. Using boolean math is the best way to go about this, with a concept called "flags".

Notice how the final value assigned into the _mapArray is always equal to 16 - value (when removing the decimal point, and converting the value to binary). Example: 1.111f = 0b1111 in binary, = 15 in decimal. 16-15 = 1, your intended value.

Since this holds true for all of your cases, we can set each bit within the using the OR operation:

    0100
|=  0010
---------
    0110

The final implementation then would look something like this:

private void NodeEnumeration()
{
    //for each node in _mapArray
    for(int i = 0; i < _mapSize; i  )
    {
        for(int e = 0; e < _mapSize; e  )
        {
            //if node value is not 0
            if(_mapArray[i, e] != 0)
            {
                int code = 0; //change our code to be an integer. we could go all the way down to a byte, if you wanted.
                //Left
                if(e != 0)
                {
                    _surroundingNodesPositions[0].x = e - 1;
                    _surroundingNodesPositions[0].y = i;

                    if(_mapArray[(int)_surroundingNodesPositions[0].y, (int)_surroundingNodesPositions[0].x] > 0)
                    {
                        code |= 0b1000; //set the 4th bit in this case. Equivalent to  = 8
                    }
                }
                //Up
                if(i != 0)
                {
                    _surroundingNodesPositions[1].x = e;
                    _surroundingNodesPositions[1].y = i - 1;
                    if(_mapArray[(int)_surroundingNodesPositions[1].y, (int)_surroundingNodesPositions[1].x] > 0)
                    {
                        code |= 0b0100; //set the 3rd bit in this case. Equivalent to  = 4
                    }
                }
                //Right
                if(e != _mapSize - 1)
                {
                    _surroundingNodesPositions[2].x = e   1;
                    _surroundingNodesPositions[2].y = i;
                    if(_mapArray[(int)_surroundingNodesPositions[2].y, (int)_surroundingNodesPositions[2].x] > 0)
                    {
                        code |= 0b0010; //set the 2nd bit in this case. Equivalent to  = 2
                    }
                }
                //Down
                if(i != _mapSize - 1)
                {
                    _surroundingNodesPositions[3].x = e;
                    _surroundingNodesPositions[3].y = i   1;
                    if(_mapArray[(int)_surroundingNodesPositions[3].y, (int)_surroundingNodesPositions[3].x] > 0)
                    {
                        code |= 0b0001; //Set the 1st bit in this case. Equivalent to  = 1
                    }
                }

                _mapArray[i, e] = 16 - flags;
            }
        }
    }
}
  • Related