我有一个简单的函数模板来计算容器的平均值:
template<typename T>
T array_average( std::vector<T>& values ) {
if( std::is_arithmetic<T>::value ) {
if( !values.empty() ) {
if( values.size() == 1 ) {
return values[0];
} else {
return (static_cast<T>( std::accumulate( values.begin(), values.end(), 0 ) ) / static_cast<T>( values.size() ) );
}
} else {
throw std::runtime_error( "Can not take average of an empty container" );
}
} else {
throw std::runtime_error( "T is not of an arithmetic type" );
}
}
我添加在static_cast<>
尝试将计算强制为所需类型<T>
.
当我在 main 中使用uint64_t
std::vector<uint64_t> values{ 1,2,3,4,5,6,7,8,9,10,11,12 };
std::cout << array_average( values ) << '\n';
此代码确实会产生 MSVC 的编译器警告C4244
由于转换可能会丢失数据,但它运行正常,这给了我预期的结果并打印出来6
到控制台。这是正确的,因为实际值是6.5
但由于整数除法的截断6
是正确的。
现在如果我使用上面的函数来代替:
std::vector<double> values { 2.0, 3.5, 4.5, 6.7, 8.9 };
std::cout << array_average( values2 ) << '\n';
这应该给我一个结果5.12
然而它正在显示4.6
反而。这也给了我与上面相同的编译器警告,但它运行时没有运行时错误(执行中断),但给了我不正确的结果。
我不确定我的函数中的错误在哪里。我不知道这是否是由于编译器警告所致,或者是否是我设计函数本身的方式。
-Edit-
用户建议这可能与此重复Q/A https://stackoverflow.com/questions/20735841/why-is-the-stdaccumulate-function-showing-the-wrong-sum-of-a-vectordouble我无法反驳它是否回答了我的问题这一事实。在问这个问题时;我不知道该错误是由于使用不当造成的std::accumulate
本身。我不确定它是否来自编译器警告,该警告与由于转换可能导致的数据丢失有关,或者我是否将其转换错误,或者是否是我一般实现此函数的方式。在提供链接之前,我已经接受了在此页面上找到的答案。我将保留此问答以供将来参考和读者!除此之外,我确实很欣赏提供的链接,因为它确实有助于了解错误在我的代码中的位置、错误是什么以及导致错误的原因,以及除了本页上接受的答案之外如何正确修复它。