#c #matlab #precision
#c #matlab #точность
Вопрос:
У меня проблема с точностью. Я должен сделать так, чтобы мой код c имел ту же точность, что и matlab. В matlab у меня есть скрипт, который выполняет некоторые действия с числами и т. Д. Я получил код на c , который выполняет то же самое, что и этот скрипт. Вывод на одном и том же входе отличается: ( Я обнаружил, что в моем скрипте, когда я пытаюсь 104> = 104, он возвращает false . Я пытался использовать format 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) amp;amp; (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
У меня возникли проблемы в else, который находится в строке 12. tx и ty eqauls 0.707106781186547 или 1 — 0.707106781186547. Значения из d_image находятся в диапазоне от 0 до 255. N — значение 0 ..255 для интерполяции 4 пикселей из изображения. d_C — значение 0.255. До сих пор не знаю, почему matlab показывает, что, когда у меня есть N значений типа: x x x 140.0000 140.0000 и в d_C: x x x 140 x. 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.
Комментарии:
1. Вы хотите сказать, что у вас один и тот же набор вычислений, выполняемых в Matlab и C , на идентичных
double
входных данных, которые дают разные результаты? Если да, пожалуйста, опубликуйте вычисления, которые вы выполняете, как в Matlab, так и в C .2. Ваша проблема не в том, что вы думаете.
3.
104>=104
всегда верно во всех известных системах программирования. Вы не рассказываете нам правдивую историю. Пока вы не сможете выработать некоторые точные точные детали, вы тратите наше время (и свое собственное).4. @DavidHeffernan Я думаю, что он просто думает, что это 104.
104.000 >= 104.0000001
неверно, но matlabdisp
оба числа одинаковы.
Ответ №1:
Matlab использует двойную точность. Вы можете использовать двойной тип C . Это должно сделать большинство вещей похожими, но не на 100%. Как заметил кто-то еще, это, вероятно, не источник вашей проблемы. Либо есть разница в алгоритмах, либо это может быть что-то вроде библиотечной функции, определенной по-разному в Matlab и в C . Например, std() Matlab делится на (n-1), а ваш код может делиться на n .
Комментарии:
1. В библиотеке C есть функция стандартного отклонения?
Ответ №2:
Во-первых, как правило, никогда не рекомендуется сравнивать переменные с плавающей запятой напрямую. Вместо, например, вместо if (nr >= 104)
вы должны использовать if (nr >= 104-e)
, где e — небольшое число, например 0.00001
.
Однако где-то в вашем скрипте должна быть какая-то серьезная ошибка при занижении выборки или округлении, потому что получение 50050 вместо 50000 не соответствует пределу обычной неточности с плавающей запятой. Например, Matlab может иметь шаг всего 15 цифр!
Я предполагаю, что в вашем коде есть некоторые проблемы с приведением, например
int i;
double d;
// ...
d = i/3 * d;
will даст очень неточный результат, потому что у вас есть целочисленное деление. d = (double)i/3 * d
или d = i/3. * d
даст гораздо более точный результат.
Приведенный выше пример НЕ вызовет никаких проблем в Matlab, потому что там по умолчанию все уже является числом с плавающей запятой, поэтому подобная проблема может быть связана с различиями в результатах кода c и Matlab.
Просмотр ваших вычислений очень поможет в поиске того, что пошло не так.
Редактировать: В c и c , если вы сравниваете double с целым числом того же значения, у вас есть очень высокая вероятность того, что они не будут равны. То же самое с двумя двойными, но вам может повезти, если вы выполните для них точно такие же вычисления. Даже в Matlab это опасно, и, возможно, вам просто повезло, что, поскольку оба являются двойными, оба были усечены одинаково. По вашему недавнему редактированию кажется, что проблема в том, где вы оцениваете свой массив. Вы никогда не должны использовать == или != при сравнении чисел с плавающей запятой или удвоений в c (или на любых языках, когда вы используете переменные с плавающей запятой). Правильный способ сравнения — проверить, находятся ли они на небольшом расстоянии друг от друга.
Пример: использование == или != для сравнения двух двойников похоже на сравнение веса двух объектов путем подсчета количества атомов в них и принятия решения о том, что они не равны, даже если между ними есть разница в один атом.
Ответ №3:
MATLAB использует двойную точность, если вы не скажете иначе. Любые различия, которые вы видите при идентичной реализации в C , будут вызваны ошибками с плавающей запятой.