Mar*_*dik 4 c++ sorting algorithm qt gcc
我已经意识到,为了使快速排序工作,所有的无限性都必须是平等的.
换句话说,这样的标准是不够的:
class Entity
{
public:
float value() const;
bool valueIsInfinite() const;
};
class Criterium
{
bool operator()(Entity left, Entity right)const
{
if (left.valueIsInfinite())
return false;
return left.value() < right.value();
}
}
const Criterium criterium;
QVector<Entity> container;
qSort<container.begin(), container .end(), criterium>
Run Code Online (Sandbox Code Playgroud)
这种排序失败了,因为根据标准并非所有无穷大都是相等的.不平等取决于实体进入运营商的顺序.我发现,这样的排序失败了.
我需要这样的东西:
class Criterium
{
bool operator()(Entity left, Entity right)const
{
if (left.valueIsInfinite() && right.valueIsInfinite())
return false;
if (left.valueIsInfinite() && !right.valueIsInfinite())
return false;
if (!left.valueIsInfinite() && right.valueIsInfinite())
return true;
return left.value() < right.value();
}
}
Run Code Online (Sandbox Code Playgroud)
但是假设不是
float Entity::value() const;
bool Entity::valueIsInfinite() const;
Run Code Online (Sandbox Code Playgroud)
方法,我想用
float Entity::value() const;
Run Code Online (Sandbox Code Playgroud)
让它回归
std::numeric_limits<float>::infinity();
Run Code Online (Sandbox Code Playgroud)
在哪些情况下
bool Entity::valueIsInfinite() const;
Run Code Online (Sandbox Code Playgroud)
会回归真实.
现在我测试了这种方法,它似乎工作.但我担心其他可能出现无限的方式.例如:
float otherInfinity = exp(std::numeric_limits<float>::infinity());
Run Code Online (Sandbox Code Playgroud)
这种无穷大似乎是一样的.但我想确定.我知道C++标准没有提到浮点运算实现的细节,但是如果我使用gcc,它在所有情况下都是安全的吗?我的意思是在gcc中创建的所有无穷大都是相同的吗?对一个浮子容器进行分类是否安全,这些浮子可能包含在不同场合出现的无穷大?
R. *_*des 10
如果没有NaNs,常规运算符就会产生无穷大<:
<是无反射的;<是反对称的;<是可传递的;<显示等价的转换.(类似属性对-∞有效)
鉴于没有 NaN的浮点数operator<上的那些属性是严格的弱排序,因此适用于标准库样式排序操作.
然而,对于NaNs,反对称性被破坏:NaN <1是假的,1 <NaN也是假的.您可以通过在所有非NaN之前或之后订购所有NaN来解决此问题,方式与您提出的策略类似:
struct Criterion
{
bool operator()(Entity left, Entity right)const
{
// NaNs come before non-NaNs
if (isnan(left.value()) && isnan(right.value()))
return false;
if (!isnan(left.value()) && isnan(right.value()))
return false;
if (isnan(left.value()) && !isnan(right.value()))
return true;
return left.value() < right.value();
}
}
Run Code Online (Sandbox Code Playgroud)
(isnan可以在C++ 11标准库中找到,或者很容易实现return x != x;)
有了这个,我们得到NaN <1为真,1 <NaN为假,而其他属性仍然成立.