Как я могу сделать точность Matlab такой же, как в C ++? - PullRequest
0 голосов
/ 11 октября 2011

У меня проблема с точностью. Я должен сделать так, чтобы мой код на C ++ имел ту же точность, что и Matlab. В Matlab у меня есть скрипт, который делает некоторые вещи с числами и т. Д. Я получил код на C ++, который делает то же самое, что и этот скрипт. Выходные данные на том же входе различны :( Я обнаружил, что в моем скрипте при попытке 104> = 104 он возвращает false. Я пытался использовать формат long, но это не помогло мне выяснить, почему его false. Оба числа являются типом double. Я подумал, что, возможно, Matlab хранит где-то реальное значение 104 и его реальное значение, как 103,9999 ... Так что я выровнял свою точность в C ++. Это также не помогло, потому что, когда Matlab возвращает мне значение 50,000 в C ++, я получил значение 50.050 с высокой точностью. Эти 2 значения получены из нескольких вычислений, таких как + или *. Можно ли сделать так, чтобы мои скрипты c ++ и matlab имели одинаковую точность?

for i = 1:neighbors
  y = spoints(i,1)+origy;
  x = spoints(i,2)+origx;
  % Calculate floors, ceils and rounds for the x and y.
  fy = floor(y); cy = ceil(y); ry = round(y);
  fx = floor(x); cx = ceil(x); rx = round(x);
  % Check if interpolation is needed.
  if (abs(x - rx) < 1e-6) && (abs(y - ry) < 1e-6)
    % Interpolation is not needed, use original datatypes
    N = image(ry:ry+dy,rx:rx+dx);
    D = N >= C; 
  else
    % Interpolation needed, use double type images 
    ty = y - fy;
    tx = x - fx;

    % Calculate the interpolation weights.
    w1 = (1 - tx) * (1 - ty);
    w2 =      tx  * (1  - ty);
    w3 = (1  - tx) *   ty ;
    w4 =      tx  *    ty ;

    %Compute interpolated pixel values
    N = w1*d_image(fy:fy+dy,fx:fx+dx) + w2*d_image(fy:fy+dy,cx:cx+dx) + ...
    w3*d_image(cy:cy+dy,fx:fx+dx) + w4*d_image(cy:cy+dy,cx:cx+dx);

    D = N >= d_C; 

 end  

У меня возникли проблемы в другом, который находится в строке 12. tx и ty eqauls 0.707106781186547 или 1 - 0.707106781186547. Значения из d_image находятся в диапазоне 0 и 255. N - это значение 0..255 интерполяции 4 пикселей из изображения. d_C - значение 0,255. До сих пор не знаю, почему Matlab показывает, что, когда у меня есть в N значения, как: х х х 140,0000 140,0000 и в d_C: х х х 140 х. D дает мне 0 на 4-ой позиции, так что 140.0000! = 140. Я отладил его, пытаясь более точно, но он все еще говорит, что его 140.00000000000000, и это все еще не 140.

int Codes::Interpolation( Point_<int> point, Point_<int> center , Mat *mat)
{


int x = center.x-point.x;
int y = center.y-point.y;

Point_<double> my;
if(x<0)
{
    if(y<0)
    {
        my.x=center.x+LEN;
        my.y=center.y+LEN;
    }   
    else
    {
        my.x=center.x+LEN;
        my.y=center.y-LEN;
    }

}
else
{
    if(y<0)
    {
        my.x=center.x-LEN;
        my.y=center.y+LEN;
    }   
    else
    {
        my.x=center.x-LEN;
        my.y=center.y-LEN;
    }
}


int a=my.x; 
int b=my.y;

double tx = my.x - a;
double ty = my.y - b;


double wage[4];
wage[0] = (1 - tx) * (1 - ty);
wage[1] =      tx  * (1 - ty);
wage[2] = (1 - tx) *      ty ;
wage[3] =      tx  *      ty ;



int values[4];

//wpisanie do tablicy 4 pixeli ktore wchodza do interpolacji
for(int i=0;i<4;i++)
{
    int val = mat->at<uchar>(Point_<int>(a+help[i].x,a+help[i].y));

    values[i]=val;
}




double moze = (wage[0]) * (values[0])  + (wage[1]) * (values[1]) + (wage[2]) * (values[2])  + (wage[3]) * (values[3]);
return moze;
}

LEN = 0,707106781186547 Значения в значениях массива на 100% совпадают со значениями Matlab.

Ответы [ 3 ]

2 голосов
/ 11 октября 2011

Matlab использует двойную точность. Вы можете использовать двойной тип C ++. Это должно сделать большинство вещей похожими, но не на 100%. Как кто-то еще заметил, это, вероятно, не источник вашей проблемы. Либо есть различия в алгоритмах, либо это может быть что-то вроде библиотечной функции, определенной по-разному в Matlab и в C ++. Например, функция std () Matlab делится на (n-1), а ваш код может делиться на n.

1 голос
/ 11 октября 2011

Во-первых, как правило, никогда не стоит сравнивать переменные с плавающей запятой напрямую. Вместо, например, вместо (nr >= 104) следует использовать if (nr >= 104-e), где e - небольшое число, например 0.00001.

Однако в вашем скрипте должна быть серьезная ошибка недостаточной выборки или округления, поскольку получение 50050 вместо 50000 не является пределом обычной неточности с плавающей запятой. Например, Matlab может иметь шаг до 15 цифр!

Полагаю, в вашем коде есть проблемы с приведением типов, например

int i;
double d;
// ...
d = i/3 * d;

даст очень неточный результат, потому что у вас целочисленное деление. d = (double)i/3 * d или d = i/3. * d даст гораздо более точный результат.

Приведенный выше пример НЕ вызовет никаких проблем в Matlab, потому что там все уже является числом с плавающей запятой по умолчанию, поэтому аналогичная проблема может быть связана с различиями в результатах кода c ++ и Matlab.

Просмотр ваших вычислений очень поможет найти, что пошло не так.

EDIT: В c и c ++, если вы сравниваете double с целым числом одинакового значения, у вас очень высока вероятность того, что они не будут равны. То же самое с двумя двойными числами, но вам может повезти, если вы выполните те же вычисления на них. Даже в Matlab это опасно, и, возможно, вам просто повезло, что, поскольку оба являются двойниками, оба были усечены одинаково. При недавнем редактировании кажется, что проблема в том, где вы оцениваете свой массив. Вы никогда не должны использовать == или! = При сравнении чисел с плавающей точкой или двойных в c ++ (или в любых языках, когда вы используете переменные с плавающей точкой). Правильный способ сделать сравнение - проверить, находятся ли они на небольшом расстоянии друг от друга.

Пример: использование == или! = Для сравнения двух двойных равнозначно сравнению веса двух объектов путем подсчета количества атомов в них и принятия решения о том, что они не равны, даже если между ними существует разница в один атом .

0 голосов
/ 11 октября 2011

MATLAB использует двойную точность, если вы не говорите иначе. Любые различия с идентичной реализацией в C ++ будут вызваны ошибками с плавающей точкой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...