sum + = x; sum / = y;行为与temp = x不同; temp / = y; sum + = temp

时间:2016-02-16 01:07:49

标签: c++ dct

我刚刚花了大约4小时来调试一个更大程序的问题,即使在修复它之后,我仍然无法弄清楚它为什么会导致问题。

编辑:

两个版本之间的主要区别。

版本1(错误):

for (int u=0;u<8;u++){
        for (int v=0;v<8;v++){
            temp += input_data[u][v] * fcosine[x/8][u] * fcosine[x%8][v];
            if (!u){
                temp /= (double) sqrt(2);
            }
            if (!v){
                temp /= (double) sqrt(2);
            }
        }    
    }
    //Produces wrong result
out[x/8][x%8] = temp/4;

正确的输出:

for (int u=0;u<8;u++){
        for (int v=0;v<8;v++){
            temp = input[u][v] * fcosine[x/8][u] * fcosine[x%8][v];
            if (!u){
                temp /= (double) sqrt(2);
            }
            if (!v){
                temp /= (double) sqrt(2);
            }
            sum +=temp;
        }
    }      
out[x/8][x%8] = (sum/4);

以下是代码的迷你版本:

#include <cstdlib>
#include<iostream>
#include <math.h>
#define PI 3.1415926535897932384626433832795 // the value of PI
void calculate_idct(double input_data[8][8], double out[8][8], double fcosine[8][8]){
double temp;

for (int x=0;x<=64;x++){
    temp = 0.0;

    for (int u=0;u<8;u++){
        for (int v=0;v<8;v++){
            temp += input_data[u][v] * fcosine[x/8][u] * fcosine[x%8][v];
            if (!u){
                temp /= (double) sqrt(2);
            }
            if (!v){
                temp /= (double) sqrt(2);
            }
        }    
    }
    //Produces wrong result
    out[x/8][x%8] = temp/4;
    }

}

void calculate_idct2(double input[8][8], double out[8][8], double fcosine[8][8]){
double temp, sum;
for (int x =0;x<=64;x++){
    sum = 0;

    for (int u=0;u<8;u++){
        for (int v=0;v<8;v++){
            temp = input[u][v] * fcosine[x/8][u] * fcosine[x%8][v];
            if (!u){
                temp /= (double) sqrt(2);
            }
            if (!v){
                temp /= (double) sqrt(2);
            }
            sum +=temp;
        }
    }

    out[x/8][x%8] = (sum/4);
    }
}

void calculate_dct(double input_data[8][8], double out64[8][8], double fcosine[8][8]) {
unsigned char   u, v, x, y;
double  temp;

// do forward discrete cosine transform
for (u = 0; u < 8; u++)
    for (v = 0; v < 8; v++) {
        temp = 0.0;
        for (x = 0; x < 8; x++)
            for (y = 0; y < 8; y++)
                temp += input_data[x][y] * fcosine[x][u] * fcosine[y][v];
        if ((u == 0) && (v == 0))
            temp /= 8.0;
        else if (((u == 0) && (v != 0)) || ((u != 0) && (v == 0)))
            temp /= (4.0*sqrt(2.0));
        else
            temp /= 4.0;
        out64[u][v] = temp;
        }
}


void make_cosine_tbl(double cosine[8][8]) {
// calculate the cosine table as defined in the formula
for (unsigned char i = 0; i < 8; i++)
    for (unsigned char j = 0; j < 8; j++)
        cosine[i][j] = cos((((2*i)+1)*j*PI)/16);
}

using namespace std;

int main(int argc, char** argv) {

double cosine[8][8];
make_cosine_tbl(cosine);

double input_data[8][8] = {{255, 0, 255, 0, 255, 0, 255, 0},
                    {0, 255, 0, 255, 0, 255, 0, 255},
                    {255, 0, 255, 0, 255, 0, 255, 0},
                    {0, 255, 0, 255, 0, 255, 0, 255},
                    {255, 0, 255, 0, 255, 0, 255, 0},
                    {0, 255, 0, 255, 0, 255, 0, 255},
                    {255, 0, 255, 0, 255, 0, 255, 0},
                    {0, 255, 0, 255, 0, 255, 0, 255} };

double out64[8][8];        

calculate_dct(input_data, out64, cosine);

double out5[8][8];

cout << "Input" << endl;
for (int i = 0;i<8;i++){
    for (int j=0;j<8;j++){
        cout << input_data[i][j] << " ";
    }
    cout << endl;
}

cout << "\n Version 1 \n " << endl;
calculate_idct(out64,out5,cosine);
for (int i = 0;i<8;i++){
    for (int j=0;j<8;j++){
        cout << out5[i][j] << " ";
    }
    cout << endl;
}



cout << "\n Version 2 \n " << endl;
calculate_idct2(out64,out5,cosine);
for (int i = 0;i<8;i++){
    for (int j=0;j<8;j++){
        cout << out5[i][j] << " ";
    }
    cout << endl;
    }


}

这是输出:

 Version 1 

60.7617 -58.7695 60.7617 -58.7695 60.7617 -58.7695 60.7617 -58.7695 
-116.404 118.396 -116.404 118.396 -116.404 118.396 -116.404 118.396 
135.3 -133.308 135.3 -133.308 135.3 -133.308 135.3 -133.308 
-139.93 141.922 -139.93 141.922 -139.93 141.922 -139.93 141.922 
141.922 -139.93 141.922 -139.93 141.922 -139.93 141.922 -139.93 
-133.308 135.3 -133.308 135.3 -133.308 135.3 -133.308 135.3 
118.396 -116.404 118.396 -116.404 118.396 -116.404 118.396 -116.404 
-58.7695 60.7617 -58.7695 60.7617 -58.7695 60.7617 -58.7695 60.7617 

 Version 2 

255 -1.42109e-14 255 -7.10543e-15 255 2.13163e-14 255 -7.10543e-14 
3.55271e-15 255 -1.13687e-13 255 -9.9476e-14 255 1.7053e-13 255 
255 -5.68434e-14 255 0 255 -2.84217e-14 255 -1.91847e-13 
6.39488e-14 255 0 255 -5.68434e-14 255 1.56319e-13 255 
255 -5.68434e-14 255 -5.68434e-14 255 -2.84217e-14 255 -1.27898e-13 
7.10543e-15 255 0 255 0 255 2.13163e-13 255 
255 2.98428e-13 255 2.55795e-13 255 2.13163e-13 255 1.52767e-13 
3.55271e-15 255 -4.9738e-14 255 -2.84217e-14 255 1.74083e-13 255 

版本2是正确的,但版本1没有接近正确的地方。

我让这个程序正常运行,但我很好奇为什么会有这么大的差异。

1 个答案:

答案 0 :(得分:2)

            temp = input[u][v] * fcosine[x][u] * fcosine[y][v];
            //I don't get it at all, but making the above line a 
                //                         += gives the wrong result

简化为:

temp = 0;
for (i = 1; i < 3; i++) {
  temp = 1;
}
// temp is 1

temp = 0;
for (i = 1; i < 3; i++) {
  temp += 1;
}
// temp is 2

为什么您希望代码与++=的工作方式相同?

此外,您(应该)在temp中总结内容然后在添加到sum之前将其除去;但如果您之间没有清空temp,则您的分部会多次应用于之前的xy结果:

100 / 4 + 100 / 4

不同
(100 / 4 + 100) / 4