【问题标题】:C++ template operator gives wrong result when subtracting a scalar from a vector从向量中减去标量时,C++ 模板运算符给出错误的结果
【发布时间】:2016-07-17 00:38:47
【问题描述】:

我正在尝试制作一个模板运算符函数,用于从向量中减去标量并将结果返回到向量中。下面的功能是我能够想出的:

// 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;
}

但是,当尝试从向量 (int) 中减去标量 (float) 时,结果不正确。我怀疑问题是因为操作数经历了通常的算术转换,其中包括积分提升。

DEMO

【问题讨论】:

  • “不正确”和“错误结果”不是有用的问题描述。一个简单的测试会产生预期的结果,使用std::vector&lt;int&gt;float 标量会产生具有正确值的std::vector&lt;float&gt; 结果。无法重现。定义“错误的结果”。
  • @Sam Varshavchik,不确定您所说的“无法重现”是什么意思——演示的目的是重现问题。无论如何,示例显示:v - s = (1, 2, 3) - 2.1 = (-1.1, -0.0999999, 0.9),这是错误的。正确的结果是向量:[-1.1f, -0.1f, 0.9f]。令我困惑的是,第二个元素产生 -0.0999999 而其他元素是正确的。

标签: c++ templates lambda integer-promotion


【解决方案1】:

这与模板无关,而是浮点数并不精确。

这会产生您在 cmets 中特别引用的相同“错误结果”:

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

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

    return 0;
}

尝试自己编译,看看结果如何。

也是 -0.0999999。

欢迎来到浮点数学的奇妙世界。

如果您需要精确的固定精度数学,可以使用专门的库来实现它。

【讨论】:

  • 你是对的,它与模板无关,只是 C/C++ 浮点运算不精确。我尝试在我的相等运算符中使用 Bruce Dawson (randomascii.wordpress.com/2012/02/25/…) 的“AlmostEqual2sComplement”方法。仍然需要一些调整。
猜你喜欢
  • 2012-09-29
  • 2020-06-25
  • 1970-01-01
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
  • 2015-06-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多