Tiny numbers instead of zero?

I am doing a matrix class (as a training exercise), and I collided and issued, checking my inverse function.

I introduce an arbitrary matrix as such:

2 1 1
1 2 1
1 1 2

And I got it to calculate the opposite, and I got the correct result:

0.75 -0.25 -0.25
-0.25 0.75 -0.25
-0.25 -0.25 0.75

But when I tried to multiply these two together to make sure that I got the identification matrix, I get:

1 5.5111512e-017 0
0 1 0
-1.11022302e-0.16 0 1

Why am I getting these results? I would understand if I multiply strange numbers, where I could understand some rounding errors, but the amount he makes is:

2 * -0.25 + 1 * 0.75 + 1 * -0.25

which is obviously 0, not 5.111512e-017

If I manually do this for calculation; eg:

std::cout << (2 * -0.25 + 1 * 0.75 + 1 * -0.25) << "\n";

I get 0 as expected?

All numbers are represented as doubles. Here is my overload overload:

Matrix operator*(const Matrix& A, const Matrix& B)
{
    if(A.get_cols() == B.get_rows())
    {
        Matrix temp(A.get_rows(), B.get_cols());
        for(unsigned m = 0; m < temp.get_rows(); ++m)
        {
            for(unsigned n = 0; n < temp.get_cols(); ++n)
            {
                for(unsigned i = 0; i < temp.get_cols(); ++i)
                {
                    temp(m, n) += A(m, i) * B(i, n);
                }
            }
        }

        return temp;
    }

    throw std::runtime_error("Bad Matrix Multiplication");
}

and access functions:

double& Matrix::operator()(unsigned r, unsigned c)
{
    return data[cols * r + c];
}

double Matrix::operator()(unsigned r, unsigned c) const
{
    return data[cols * r + c];
}

Here is the function to search for the opposite:

Matrix Inverse(Matrix& M)
{
    if(M.rows != M.cols)
    {
        throw std::runtime_error("Matrix is not square");
    }

    int r = 0;
    int c = 0;
    Matrix augment(M.rows, M.cols*2);
    augment.copy(M);

    for(r = 0; r < M.rows; ++r)
    {
        for(c = M.cols; c < M.cols * 2; ++c)
        {
            augment(r, c) = (r == (c - M.cols) ? 1.0 : 0.0);
        }
    }

    for(int R = 0; R < augment.rows; ++R)
    {
        double n = augment(R, R);
        for(c = 0; c < augment.cols; ++c)
        {
            augment(R, c) /= n;
        }

        for(r = 0; r < augment.rows; ++r)
        {
            if(r == R) { continue; }
            double a = augment(r, R);

            for(c = 0; c < augment.cols; ++c)
            {
                augment(r, c) -= a * augment(R, c);
            }
        }
    }

    Matrix inverse(M.rows, M.cols);
    for(r = 0; r < M.rows; ++r)
    {
        for(c = M.cols; c < M.cols * 2; ++c)
        {
            inverse(r, c - M.cols) = augment(r, c);
        }
    }

    return inverse;
}
+5
5

, 0.250000000000000005 , , , 0.25.

+9

:

+11

, 2 ​​. , , , .

, , . Ie, 0,25 (= 1/4), 0,75 (= 3/4) ..

+2

, , (.. 2 ^ (N) 1/(2 ^ N), N - ).

, Google .

, , inifinite-precision, , , , . , , GMP. rational, , , 64- , - . , GMP, , .

+2

This is just a simple floating point error. Even doubleon computers it’s not 100% accurate. There is simply no way to 100% accurately represent the base-10 decimal in binary with a finite number of bits.

+1
source

All Articles