依赖从任何数字类型(unsigned、int、...)到 double 的隐式提升是否安全?
Is it safe to rely on implicit promotion from any numeric type (unsigned, int, ...) to double?
我有一个图表模板 class,它采用权重类型的参数(可以是无符号、整数或双精度)。此外,为了比较双打,我使用以下类型的内联函数:
inline bool EpsLess(double x, double y, double epsilon = 1.e-10)
{
return x < y - epsilon;
}
inline bool EpsEqual(double x, double y, double epsilon = 1.e-10)
{
return !EpsLess(x,y) && !EpsLess(y,x);
}
下面class骨架中的比较器安全吗?
template <typename Weight>
class Graph
{
struct Edge
{
std::string from;
std::string to;
Weight weight;
};
struct LargestWeight
{
bool operator() (const Edge& e1, const Edge& e2) const
{
if (EpsEqual(e1.weight == e2.weight))
if (e1.from == e2.from)
return e1.to < e2.to;
else
return e1.from < e2.from;
return EpsLess(e2.weight, e1.weight);
}
};
// .. other stuff
};
当 Weight 类型为 unsigned 或 int 时,我会遇到无法预料的后果吗?或者有没有更好的方法来实现双重比较?
这正是模板的用途。
我建议您在仅使用 <
和 ==
运算符的模板 class 中实现 EpsLess
()。类似于:
template<typename Type> Compare {
public:
template<typename Ignore>
inline bool EpsLess(Type x, Type y, Ignore epsilon = Ignore())
{
return x < y;
}
};
然后将其专门化为 double:
template<> Compare<double> {
public:
inline bool EpsLess(double x, double y, double epsilon = 1.e-10)
{
return x < y - epsilon;
}
};
您可以这样调用它:
if (Compare<Weight>::EpsEqual(e1.weight, e2.weight))
这将避免对非双重情况进行大量无用的工作,并将其移交给普通的 <
运算符。
那么,你的家庭作业是根据新的 EpsLess
() 重新实现 EpsEqual
() 作为模板函数本身。
不,您不能在所有情况下都相信整数到双倍的转换。
从整数到双精度的转换不能总是在不损失精度的情况下完成。因此,如果 Weight 是可以容纳大值的整数类型,例如一个size_t
所有 32 位整数都可以毫无问题地转换(也就是精度损失)。
我有一个图表模板 class,它采用权重类型的参数(可以是无符号、整数或双精度)。此外,为了比较双打,我使用以下类型的内联函数:
inline bool EpsLess(double x, double y, double epsilon = 1.e-10)
{
return x < y - epsilon;
}
inline bool EpsEqual(double x, double y, double epsilon = 1.e-10)
{
return !EpsLess(x,y) && !EpsLess(y,x);
}
下面class骨架中的比较器安全吗?
template <typename Weight>
class Graph
{
struct Edge
{
std::string from;
std::string to;
Weight weight;
};
struct LargestWeight
{
bool operator() (const Edge& e1, const Edge& e2) const
{
if (EpsEqual(e1.weight == e2.weight))
if (e1.from == e2.from)
return e1.to < e2.to;
else
return e1.from < e2.from;
return EpsLess(e2.weight, e1.weight);
}
};
// .. other stuff
};
当 Weight 类型为 unsigned 或 int 时,我会遇到无法预料的后果吗?或者有没有更好的方法来实现双重比较?
这正是模板的用途。
我建议您在仅使用 <
和 ==
运算符的模板 class 中实现 EpsLess
()。类似于:
template<typename Type> Compare {
public:
template<typename Ignore>
inline bool EpsLess(Type x, Type y, Ignore epsilon = Ignore())
{
return x < y;
}
};
然后将其专门化为 double:
template<> Compare<double> {
public:
inline bool EpsLess(double x, double y, double epsilon = 1.e-10)
{
return x < y - epsilon;
}
};
您可以这样调用它:
if (Compare<Weight>::EpsEqual(e1.weight, e2.weight))
这将避免对非双重情况进行大量无用的工作,并将其移交给普通的 <
运算符。
那么,你的家庭作业是根据新的 EpsLess
() 重新实现 EpsEqual
() 作为模板函数本身。
不,您不能在所有情况下都相信整数到双倍的转换。
从整数到双精度的转换不能总是在不损失精度的情况下完成。因此,如果 Weight 是可以容纳大值的整数类型,例如一个size_t
所有 32 位整数都可以毫无问题地转换(也就是精度损失)。