1

I'm trying to implement Linspace in c++ I created some random tests and have a problem with precision I don't understand why.

c++ implementation

std::vector<double> libcalc::linear_space(double a, double b, unsigned int n)
{
    std::vector<double> array(n,a);
    //return an empty array if number of spaces is 0
    //return a if number of spaces is 1
    if (n <= 1 || fabs(a - b) < std::numeric_limits<double>::epsilon())
    {
        return array;
    }

    //we want to be sure we get exactly b in the end
    for (unsigned int i = 0; i < n-1; ++i)
    {
        array[i] = a + ((b - a)*i)/(n-1);
    }
    array[n - 1] = b;
    return array;
}

Catch unit test frame work test

auto reverse = [](std::vector<double> const& x)
{
    std::vector<double> output(x.size());
    std::reverse_copy(x.begin(), x.end(), output.begin());

    return output;
};

SCENARIO("Any linear space (a, b) with two or more points will be same as"
    " the reversed linear space of (b, a)")
{
    GIVEN("a range of points to check starting from 2")
    {
        unsigned int starting_point = 2;
        unsigned int ending_point = 10;

        THEN("the linear space (a, b) is same as reversed linear space (b, a)")
        {
            for (unsigned int n = starting_point; n < ending_point; ++n)
            {
                auto a = any_value();
                auto b = any_value();

                auto x = linear_space(a, b, n);
                auto y = reverse(linear_space(b, a, n));
                INFO("a: " << a);
                INFO("b: " << b);
                INFO("n: " << n);
                REQUIRE(x.size() == y.size());
                CHECK(x == y);
            }
        }
    }
}

the c++ code results are

  CHECK( x == y )
with expansion:
  { -296336583.43100381, 273999144.43620467, 844334872.30341315, 1414670600.
  1706216, 1985006328.0378299 }
  ==
  { -296336583.43100381, 273999144.43620443, 844334872.30341291, 1414670600.
  1706214, 1985006328.0378299 }
with messages:
  a: -2.96337e+008
  b: 1.98501e+009
  n: 5

the matlab results have better precision for forward or reverse linspace

linspace(-296336583.4310038, 1985006328.0378299,5)

ans =  1.0e+09 *

  Columns 1 through 4

  -0.296336583431004   0.273999144436205   0.844334872303413   1.414670600170622

  Column 5

   1.985006328037830


linspace(1985006328.0378299,-296336583.4310038,5)

ans =

   1.0e+09 *

  Columns 1 through 4

   1.985006328037830   1.414670600170621   0.844334872303413   0.273999144436204

  Column 5

  -0.296336583431004

as you can see the number are very much a like but... not exactly the same. Can you please help why is this?

Gilad
  • 6,437
  • 14
  • 61
  • 119
  • You need to show the MATLAB tests also – Ander Biguri Jun 29 '17 at 08:36
  • @AnderBiguri I add them – Gilad Jun 29 '17 at 09:00
  • 1
    Floating point math is weird (technically the order of the calculations matters), probably you should "cheat" and calculate the steps moving simmetrically from the extremes using both `a + ((b - a)*i)/(n-1)` and say, `b + ((a - b)*i)/(n-1)`. – Bob__ Jun 29 '17 at 09:02
  • "the matlab results are exactly the same numbers is forward or reverse linspace" **false** – Ander Biguri Jun 29 '17 at 09:02
  • @AnderBiguri you are write! I didn't noticed that, but they have better percision – Gilad Jun 29 '17 at 09:03
  • 3
    Floating point arithmetic are not commutative. `a*b*c` is not `c*b*a`. You can not expect them to be the same. If you do maths in a computer, you need to accept that this is going to happen. Probably MATLAB uses a "mathematically" equivalent line of code to compute linspace, but unless it is exactly character by character the same line, the results will be different – Ander Biguri Jun 29 '17 at 09:04
  • @AnderBiguri thanks so I only need to revise my tests – Gilad Jun 29 '17 at 11:24

0 Answers0