gpt4 book ai didi

C++ 如何简化这个模板,使其不专门化?

转载 作者:行者123 更新时间:2023-12-01 14:49:08 26 4
gpt4 key购买 nike

我试图建立一个模板来比较基于 https://floating-point-gui.de/errors/comparison/ 的浮点数或 double 数对于 C++。该版本要求将 epsilon 值传递给代码,但我想为系统使用默认的 FLT_EPSILON、FLT_MIN、FLT_MAX、DBL_EPSILON、DBL_MIN 和 DBL_MAX,并且在 float.h 中可用。

有没有办法在如下语句中使用 typename:

T epsilon;
if ( T == DBL_TYPE ) epsilon = DBL_EPSILON
else epsilon = FLT_EPSILON ????

这将使例程成为例程,因此我不必专门化它,这会导致单一定义规则 (ODR) 问题。

我是模板的新手,所以我不知道如何提问。
template <typename T>
bool IsNearEqual( T test_1, T test_2 )
{
if ( test_1 == test_2 ) return true;
return false;
}

template <>
bool IsNearEqual( float test_1, float test_2 )
{
const float FLT_NORMAL = ( (long)1 << 23 ) * FLT_EPSILON;
if ( test_1 == test_2 )
{ // shortcut, handles infinities
return true;
}
float test_1Abs = dfAbs( test_1 );
float test_2Abs = dfAbs( test_2 );
float test_1_2AbsDif = dfAbs( test_1 - test_2 );
float test_1_2Sum = test_1Abs + test_2Abs;

if ( test_1 == 0 || test_2 == 0 || test_1_2Sum < FLT_NORMAL )
{ // test_1 or test_2 is zero or both are extremely close to it relative error is less meaningful here
return test_1_2AbsDif < ( FLT_EPSILON * FLT_NORMAL );
}
else
{ // use relative error
return test_1_2AbsDif / dfMin( test_1_2Sum, FLT_MIN ) < FLT_EPSILON;
}
return false;
}
template <>
bool IsNearEqual( double test_1, double test_2 )
{
const double DBL_NORMAL = ( (long long)1 << 52 ) * DBL_EPSILON;

if ( test_1 == test_2 )
{ // shortcut, handles infinities
return true;
}
double test_1Abs = dfAbs( test_1 );
double test_2Abs = dfAbs( test_2 );
double test_1_2AbsDif = dfAbs( test_1 - test_2 );
double test_1_2Sum = test_1Abs + test_2Abs;

if ( test_1 == 0 || test_2 == 0 || test_1_2Sum < DBL_NORMAL )
{ // test_1 or test_2 is zero or both are extremely close to it relative error is less meaningful here
return test_1_2AbsDif < ( DBL_EPSILON * DBL_NORMAL );
}
else
{ // use relative error
return test_1_2AbsDif / dfMin( test_1_2Sum, DBL_MAX ) < DBL_EPSILON;
}
return false;
}

template <typename T, typename U>
T dfMin( T test_1, U test_2 )
{
T out;
out = test_1;
if ( out > test_2 ) out = (T)test_2;

return out;
}

template <typename T, typename U>
T dfMax( T test_1, U test_2 )
{
T out;
out = test_1;
if ( test_2 > out ) out = (T)test_2;

return out;
}

template <typename T>
T dfAbs( T test )
{
T out;
out = test;
if ( test < 0.0 ) out = -test;

return out;
}


谢谢,
罗纳克

最佳答案

这是带有一点 SFINAE 和使用 std::numeric_limits 的代码正如评论中所建议的那样。

template <class T, std::enable_if_t<std::is_floating_point<T>{}>* = nullptr>
bool IsNearEqual(T test_1, T test_2) {
using nl = std::numeric_limits<T>;

const T NORMAL = ((long)1 << nl::digits) * nl::epsilon();
if (test_1 == test_2) { // shortcut, handles infinities
return true;
}
float test_1Abs = dfAbs(test_1);
float test_2Abs = dfAbs(test_2);
float test_1_2AbsDif = dfAbs(test_1 - test_2);
float test_1_2Sum = test_1Abs + test_2Abs;

if (test_1 == 0 || test_2 == 0 ||
test_1_2Sum < NORMAL) { // test_1 or test_2 is zero or both are extremely
// close to it relative error is less meaningful
// here
return test_1_2AbsDif < (nl::epsilon() * NORMAL);
} else { // use relative error
return test_1_2AbsDif / dfMin(test_1_2Sum, nl::max()) < nl::epsilon();
}
return false;
}

关于C++ 如何简化这个模板,使其不专门化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59516317/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com