Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 多重双精度的词典排序_Algorithm_Numeric - Fatal编程技术网

Algorithm 多重双精度的词典排序

Algorithm 多重双精度的词典排序,algorithm,numeric,Algorithm,Numeric,考虑一类类型double class path_cost { double length; double time; }; 如果我想按字典顺序排列路径成本列表,我有一个问题。请继续阅读:) 如果我对等式测试使用完全相等,就像这样 bool operator<(const path_cost& rhs) const { if (length == rhs.length) return time < rhs.time; return length <

考虑一类类型double

class path_cost {
   double length;
   double time;
};
如果我想按字典顺序排列
路径成本列表
,我有一个问题。请继续阅读:)

如果我对等式测试使用完全相等,就像这样

bool operator<(const path_cost& rhs) const {
   if (length == rhs.length) return time < rhs.time;
   return length < rhs.length;
}

bool运算符我不熟悉您的应用程序,但我愿意打赌,图形中点之间的距离差比浮点数字的舍入误差大很多数量级。因此,如果两个条目仅因舍入错误而不同,那么它们本质上是相同的,并且它们在列表中的显示顺序没有区别。从常识的角度来看,我看没有理由担心。

普通的
双精度
s永远无法获得100%的精度。您说您担心使用公差会影响程序的正确性。你真的测试过这个吗?您的程序实际需要什么级别的精度

在大多数常见的应用中,我发现像
1e-9
这样的公差就足够了。当然,这一切都取决于你的申请。您可以估计所需的精度级别,只需将公差设置为可接受的值


即使失败了,也意味着
double
根本不适合您的目的。这种情况极不可能发生,但如果您需要非常高精度的计算,则可能会出现这种情况。在这种情况下,您必须使用任意精度的包(例如Java中的BigDecimal或类似于C的东西)。同样,只有在没有其他方法时才选择此选项

我认为你不能做你想做的事。本质上,你似乎是在说,在某些情况下,你想忽略a>b的事实,假装a=b。我很确定你可以构造一个证明,如果a和b的差值小于某个值,那么a和b对于a和b的所有值都是等价的。大致如下:


对于C和两个数字a和B的公差,在不丧失一般性的情况下,a>B存在
D(n)=B+n*(C/10)
其中
0我可以想到两种解决方案

您可以仔细选择一种排序算法,在比较不及物性时不会失败。例如,快速排序不应该失败,至少如果您自己实现它的话。(如果您担心快速排序的最坏情况,可以先将列表随机化,然后对其排序。)

或者你可以扩展你的容差补丁,使它成为一个等价关系,你可以恢复传递性。有标准来完成任何关系到等价关系。应用union find后,您可以使用一致值(例如平均值)替换每个等价类中的长度,然后执行您想要执行的排序。对浮点数进行修改以防止虚假的重新排序感觉有点奇怪,但它应该可以工作



事实上,白痴说得很对。您可以先按长度排序,然后将公差范围内的邻居链接在一起,然后在第二个键上的每个组内进行次排序,而不是联合和查找。这与我的第二个建议的结果相同,但它是一个更简单的实现。

您真的只想要一个比较函数吗

你为什么不先按长度排序,然后按你认为相同的长度分组,然后按时间在每组中排序


一旦按长度排序,您就可以应用所需的任何启发式方法来确定长度的“相等”并进行分组。

我已经尝试过了,但失败了。问题是,在一定的概率下,传递性失败,应用程序出错。我有一个解决方法(包括在中间结果中使用longdouble),但我想知道一般的问题。当然,以前有人看过这个问题吗?公差与我们使用的非常接近。数字部分来自标签设置/a*算法,部分来自coin或LP解决方案。正如我上面所写的,问题是当传递性失败时,常见的排序算法不再是定义良好的,在我的例子中,它们只是崩溃。如果不尝试调整数字,就不会出现这种失败。如果它们的数量一直很小,那么它们就会一直正确地被分类。浮点数没有什么神秘之处,它们在比较过程中不会改变值。小结:不要弄乱数字,你就不会有传递性问题。我没有调整任何数字,所以这不是问题所在。我记得,问题是排序范围被推断为包含值,但实际上没有。因此,它最终运行到范围的末尾,进入未分配内存=>crash。您会注意到,例如std::sort要求排序运算符是“严格弱排序”,这意味着传递性。这实际上不是一个坏主意,尽管它很简单。这需要做一些工作才能得到正确的结果,但这肯定是可能的。排序算法非常、非常偶尔地崩溃——我们只在一个数据集上出现问题,而且只有在使用-O2编译数据集时才出现问题(我们怀疑这与协处理器的80位内部表示有关)。崩溃发生的原因是,由于排序的原因,算法离开了列表的一端。这是有道理的。我想知道是否有某种魔力使它能够以某种方式测试比较函数,看看它是否可行。如果它那样做的话,我会留下深刻的印象谢谢你提出一个有趣的问题。我以前真的没有想过这类事情。:)
bool operator<(const path_cost& rhs) const {
   if (std::fabs(length-rhs.length)<1-e6)) return time < rhs.time;
   return length < rhs.length;
}