Я пытаюсь понять, почему вычисление определителя матрицы 3x3 таким образом дает неверные результаты:
#include <iostream>
#include <array>
#include <vector>
int main(int argc, char const *argv[])
{
const int dim = 3;
std::vector<std::vector<float>> data;
data.resize(dim, std::vector<float>(dim, 0));
std::array<float, dim*dim> myArray = {
-1000.0, -1000.0, -1000.0,
-1000.0, -1000.0, -1000.0,
-1000.0, -1000.0, -999.0
};
for(int i = 0; i < dim; i++){
for(int j = 0; j < dim; j++){
data[i][j] = myArray[dim*i + j];
}
}
float det =
data[0][0] * data[1][1] * data[2][2] +
data[0][1] * data[1][2] * data[2][0] +
data[0][2] * data[2][1] * data[1][0] -
data[2][0] * data[1][1] * data[0][2] -
data[0][0] * data[1][2] * data[2][1] -
data[1][0] * data[0][1] * data[2][2];
float anotherDet = 0;
for(int i = 0; i < 2; i++){
anotherDet = anotherDet + 1000 * 1000 * 1000;
}
for(int i = 0; i < 2; i++){
anotherDet = anotherDet - 1000 * 1000 * 1000;
}
anotherDet = anotherDet - 1000 * 1000 * 999;
anotherDet = anotherDet + 1000 * 1000 * 999;
std::cout << det << " " << anotherDet << std::endl;
return 0;
}
Результатом этого кода является -64 0
, тогда как действительный определитель такой матрицы должен быть нулевым. Я подозреваю, что ошибка связана с точностью с плавающей запятой, но я до сих пор не могу понять, почему возникают такие несоответствия.
Я попробовал отладить и действительно обнаружил, что существует продолжающаяся ошибка округления. -2999000060
- это значение det
в середине этой большой суммы.
Но если я попробую следующее:
float det2 =
1000 * 1000 * 1000 +
1000 * 1000 * 1000 +
1000 * 1000 * 999 -
1000 * 1000 * 1000 -
1000 * 1000 * 1000 -
1000 * 1000 * 999;
Это даст правильное значение 0, но только потому что это операция arithmeti c, и поэтому ошибок округления нет.
Edit: теперь я понимаю, как операции с такими большими числами могут нести некоторую ошибку округления.