2016-02-16 1 views
-3

Je viens juste de passer ~ 4 heures à déboguer un problème que j'avais avec un programme plus grand, et même après l'avoir corrigé, je n'arrive toujours pas à comprendre pourquoi cela causait un problème.somme + = x; somme/= y; se comporte différemment de temp = x; temp/= y; sum + = temp

EDIT:

Les principales différences entre les deux versions.

Version 1 (Mauvais):

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; 

CORRECT SORTIE:

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); 

est ici la version mini du code:

#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; 
    } 


} 

Voici la sortie:

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 

La version 2 est correcte, mais la version 1 est loin d'être correcte.

J'ai réussi à faire fonctionner le programme, mais je suis curieux de savoir pourquoi il y avait une si grande différence.

+5

Vous savez que c et C++ sont des langues différentes n'est-ce pas? En outre, votre code est laid à le lire. Formatez-la avec plus d'espaces et essayez d'imbriquer moins de boucles 'for' utilisez des fonctions pour cela et vous pourriez trouver le problème. Mais comme c'est il est trop difficile de trouver le problème et il semble être causé par une faute de frappe ou quelque chose de similaire, donc pas d'intérêt pour le moment. –

+0

Quel est le problème? SO n'est pas un service de débogage. – Olaf

+0

Et ce n'est pas du code C! Utilisez les balises correctes! – Olaf

Répondre

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 

simplifié:

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 

Pourquoi le code fonctionne même avec + et += voulez-vous attendre?

De plus, vous êtes (supposé être) en train de récapituler des données dans temp puis de les diviser avant de les ajouter à sum; mais si vous ne videz temp entre les deux, votre division soit appliquée plusieurs fois à plus tôt x et y résultats:

100/4 + 100/4 

est différent de

(100/4 + 100)/4 
+0

Non, ils devraient se produire en même temps. Quelque chose comme: Summation (AxBxC/(ExF)) –

+1

Il n'y a pas A, B, C, E ou F dans votre code. Nommez la première itération 'temp' dans le code correct après la ligne marquée comme' temp1'; deuxième itération 'temp2'. Votre 'somme' après deux itérations est' temp1/sqrt (2) + temp2/sqrt (2) '. Dans votre mauvais code, votre 'temp' dans la deuxième itération est en fait' (temp1/sqrt (2) + temp2)/sqrt (2) '. Suivez simplement le code. – Amadan