-2

I am trying to make a template operator function for subtracting a scalar from a vector and return the result in a vector. The function below is what I have been able to come up with:

// vector - scalar
template<typename T1, typename T2>
auto operator - ( const Vector<T1> & lhs, const T2 & scalar )-> Vector<std::common_type_t<T1,T2>>
{
   using T3 = std::common_type_t<T1, T2>;
   Vector<T3> result;
   result.base.reserve( lhs.base.size() );
   std::transform( lhs.base.begin(), lhs.base.end(), std::back_inserter( result.base ),
             [&scalar]( const T3 & element ) { return element - scalar; } );
   return result;
}

However, the result is not correct when trying to subtract a scalar (float) from a vector (int). I suspect the problem is because the operands undergo the usual arithmetic conversions, which include integral promotions.

DEMO

bobster
  • 53
  • 5
  • 1
    "is not correct", and "wrong result", are not a useful problem description. A simple test produces the expected result, using `std::vector` and a `float` scalar results in a `std::vector` result with the right values. Cannot reproduce. Define "wrong result". – Sam Varshavchik Jul 17 '16 at 00:47
  • @Sam Varshavchik, not sure what you mean by "Cannot reproduce" - the purpose of the demo was to reproduce the problem. Anyway, the example shows: v - s = (1, 2, 3) - 2.1 = (-1.1, -0.0999999, 0.9), which is wrong. The correct result is the vector: [-1.1f, -0.1f, 0.9f]. What puzzles me is that the second element yields -0.0999999 and the other elements are correct. – bobster Jul 17 '16 at 01:15
  • 1
    No, these results is correct. What you are missing is the fact that [floating point numbers are not exact, and have never been exact in C++, or most modern programming languages](http://stackoverflow.com/questions/588004/is-floating-point-math-broken). – Sam Varshavchik Jul 17 '16 at 01:18

1 Answers1

1

This has nothing to do with templates, but with the fact that floating point numbers are not exact.

This produces the same "wrong result" you specifically cited in the comments:

float subtract(float a, float b)
{
    return a-b;
}

int main()
{
    std::cout << subtract(2, 2.1) << std::endl;

    return 0;
}

Try to compile this yourself, and see what the result is.

It's also -0.0999999.

Welcome to the wonderful world of floating point math.

If you need accurate fixed precision math, there are specialty libraries that implement it.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
  • You are correct, it has nothing to do with templates, just that C/C++ floating point arithmetic is not exact. I have tried using the "AlmostEqual2sComplement" method by Bruce Dawson (https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/) in my equal operator. Still needs a little tweaking. – bobster Jul 17 '16 at 01:52