对2D阵列进行多次数学运算会导致2D阵列内的值不正确

时间:2017-10-31 16:33:36

标签: c# dct

我试图在我的代码中找到麻烦的原因。 FDCTHorizontal转换2D数组中的所有数字,IDCTHorizontal应该将它们转换回来。

只有在每个方法内的一个相同元素上完成一个数学运算时,方法才能工作。如果进行了两次操作,则IDCTHorizontal返回的2D数组与输入FDCTHorizontal的数组不同。

参数differences表示2D数组中的一行。参数YX表示输出行值。

为什么我不能在两种方法中使用多个数学运算?

代码:

public static void FDCTHorizontal(ref int[] differences, ref int[] Y)
{
    for (int j = 0; j < differences.Length; j += 8) //split by 8
    {
        double[] X = new double[8];

        int indexCounter = 0;
        for (int _ = j; _ < j + 8; _++)
        {
            X[indexCounter] = differences[_];
            indexCounter++;
        }

        //1. stage
        double X0value = X[0];
        double X1value = X[1];
        double X2value = X[2];
        double X3value = X[3];
        double X4value = X[4];
        double X5value = X[5];
        double X6value = X[6];
        double X7value = X[7];

        //X[0] = X[0] + X7value; //if not commented, value when calling inverse method will not be the same
        X[7] = -X[7] + X0value;

        Y[j + 0] = Convert.ToInt32(X[0]);
        Y[j + 4] = Convert.ToInt32(X[1]);
        Y[j + 2] = Convert.ToInt32(X[2]);
        Y[j + 6] = Convert.ToInt32(X[3]);
        Y[j + 7] = Convert.ToInt32(X[4]);
        Y[j + 3] = Convert.ToInt32(X[5]);
        Y[j + 5] = Convert.ToInt32(X[6]);
        Y[j + 1] = Convert.ToInt32(X[7]); //switched order
    }
}

public static void IDCTHorizontal(ref int[] changedDifferences, ref int[] X)
{
    for (int j = 0; j < changedDifferences.Length; j += 8)
    {
        double[] Y = new double[8];
        int indexCounter = 0;
        for (int _ = j; _ < j + 8; _++)
        {
            Y[indexCounter] = changedDifferences[_];
            Y[indexCounter] = Y[indexCounter];
            indexCounter++;
        }

        double Y0value = Y[0];
        double Y1value = Y[1];
        double Y2value = Y[2];
        double Y3value = Y[3];
        double Y4value = Y[4];
        double Y5value = Y[5];
        double Y6value = Y[6];
        double Y7value = Y[7];

        //Y[0] = Y[0] - Y1value; //if not a comment, returned array does not have the right values
        Y[1] = -Y[1] + Y0value;

        X[j + 0] = Convert.ToInt32(Y[0]);
        X[j + 1] = Convert.ToInt32(Y[4]);
        X[j + 2] = Convert.ToInt32(Y[2]);
        X[j + 3] = Convert.ToInt32(Y[6]);
        X[j + 4] = Convert.ToInt32(Y[7]);
        X[j + 5] = Convert.ToInt32(Y[3]);
        X[j + 6] = Convert.ToInt32(Y[5]);
        X[j + 7] = Convert.ToInt32(Y[1]);
    }
}

1 个答案:

答案 0 :(得分:0)

除了算法的正确性之外,还有一个更大的问题:您在两次转换中执行银行家舍入。您不能指望两个操作都是可逆的,因为舍入通常不是:

假设以下转换:f(x) = x + 1.5和相反的g(x) = x - 1.5。应用这两种变换显然是一种努力:g(f(x)) = x + 1.5 - 1.5 = x

但是,如果我们向其添加舍入,则行为会更改:

f´(x) = BankersRound(x + 1.5)
g´(x) = BankersRound(x - 1.5)

x = 3
f´(3) = BankersRound(4.5) = 4 //round to the nearest even number
g´(f(3)) = BankersRound(4 - 1.5) = BankersRound(2.5) = 2 //round to the nearest even number

更新:好的,这不是问题,因为正如RufusL正确指出的那样,您只是执行加法和减法,因此在这种情况下舍入不应成为问题。但这显然引出了一个问题:为什么要使用double数组开始?如果要添加和减去整数,请使用整数数组! (或者如果您期望在中间操作中出现潜在的溢出,则为多。)