排序算法如何对容器和浮动范围进行排序?
How does sorting algorithms sort containers and ranges of floats?
既然比较 float
s 是邪恶的,那么如果我有一个 float
s 的容器,我使用一些标准库排序算法(如 std::sort
)对它进行排序,那么该算法如何排序他们?
std::vector<float> vf{2.4f, 1.05f, 1.05f, 2.39f};
std::sort( vf.begin(), vf.end() );
那么算法会比较1.05f
和1.05f
吗?
它内部是否使用类似:std::fabs( 1.05f - 1.05f ) < 0.1;
?
这也适用于 double
的容器吗?谢谢!
So does the algorithm compare 1.05f
and 1.05f
?
是
Does it internally uses something like: std::fabs( 1.05f - 1.05f ) < 0.1;
?
不,它使用 operator <
,例如1.05f < 1.05f
。它永远不需要比较是否相等,因此不需要使用 epsilon 值进行比较。
Does this apply too to containers of double
s?
是的,它适用于任何类型的容器(除非您向 std::sort
提供自己的比较功能)
Since comparing floats
is evil…
这是一个神话,是错误的。与之相关的是浮点数近似于实数的神话。
<
、<=
、>
和 >=
可以很好地对数字进行排序,==
和 !=
也可以正确比较两个数是否相等。 <
、<=
、>
和 >=
在对包含 NaN(“非数字”数据)的数据进行排序时将不会提供服务。
根据 IEEE 754 浮点运算标准和浮点格式的其他通用规范,任何浮点表示形式 ±F•be正好代表一个数字。甚至 +∞ 和 −∞ 也被认为是精确的。指定为近似实数算术的是浮点算术中的运算,而不是数字。当执行计算操作时,其结果是根据选定的舍入规则舍入到最接近的可表示数字的实数结果,但具有域错误的操作可能会产生 NaN。 (四舍五入是最常见的规则,还有其他几个。)
因此,当您对数字进行加减、乘除、取平方根或将数字从一种基数转换为另一种基数(例如将十进制字符输入为内部浮点格式)时,可能会出现舍入错误。
部分操作没有错误。比较操作没有错误。 <
、<=
、>
、>=
、==
和 !=
总是产生正确的数学结果,无论是真还是假,没有错误.因此,它们可用于对数字进行排序。 (对于 NaN,它们总是产生 false,因为 NaN 永远不会小于、等于或大于一个数字,NaN 也不会小于、等于或大于 NaN。所以 false 是正确的结果,但是这意味着这些比较对于使用 NaN 进行排序没有用。)
理解这种区别,即数字是精确的,运算可能是近似的,对于分析、设计和证明涉及浮点运算的算法至关重要。
当然,在一个数字数组中,数字可能包含早期操作的错误:它们与使用实数运算得到的数字不同。在这种情况下,数字将根据它们的实际计算值排序,而不是根据您希望它们具有的理想值排序。这不是 std::sort
正确排序数字的障碍。
要对包括 NaN 的数据进行排序,您需要一个全序谓词来报告一个数据是否比另一个数据在所需的排序顺序中早,例如报告 NaN 晚于任何非 NaN 的数据。 IEEE-754 定义了一个全序谓词,但我不能说它在 C++ 中的可用性。 (根据我试过的快速测试,std::less
似乎没有提供。)
既然比较 float
s 是邪恶的,那么如果我有一个 float
s 的容器,我使用一些标准库排序算法(如 std::sort
)对它进行排序,那么该算法如何排序他们?
std::vector<float> vf{2.4f, 1.05f, 1.05f, 2.39f};
std::sort( vf.begin(), vf.end() );
那么算法会比较
1.05f
和1.05f
吗?它内部是否使用类似:
std::fabs( 1.05f - 1.05f ) < 0.1;
?这也适用于
double
的容器吗?谢谢!
So does the algorithm compare
1.05f
and1.05f
?
是
Does it internally uses something like:
std::fabs( 1.05f - 1.05f ) < 0.1;
?
不,它使用 operator <
,例如1.05f < 1.05f
。它永远不需要比较是否相等,因此不需要使用 epsilon 值进行比较。
Does this apply too to containers of
double
s?
是的,它适用于任何类型的容器(除非您向 std::sort
提供自己的比较功能)
Since comparing
floats
is evil…
这是一个神话,是错误的。与之相关的是浮点数近似于实数的神话。
<
、<=
、>
和 >=
可以很好地对数字进行排序,==
和 !=
也可以正确比较两个数是否相等。 <
、<=
、>
和 >=
在对包含 NaN(“非数字”数据)的数据进行排序时将不会提供服务。
根据 IEEE 754 浮点运算标准和浮点格式的其他通用规范,任何浮点表示形式 ±F•be正好代表一个数字。甚至 +∞ 和 −∞ 也被认为是精确的。指定为近似实数算术的是浮点算术中的运算,而不是数字。当执行计算操作时,其结果是根据选定的舍入规则舍入到最接近的可表示数字的实数结果,但具有域错误的操作可能会产生 NaN。 (四舍五入是最常见的规则,还有其他几个。)
因此,当您对数字进行加减、乘除、取平方根或将数字从一种基数转换为另一种基数(例如将十进制字符输入为内部浮点格式)时,可能会出现舍入错误。
部分操作没有错误。比较操作没有错误。 <
、<=
、>
、>=
、==
和 !=
总是产生正确的数学结果,无论是真还是假,没有错误.因此,它们可用于对数字进行排序。 (对于 NaN,它们总是产生 false,因为 NaN 永远不会小于、等于或大于一个数字,NaN 也不会小于、等于或大于 NaN。所以 false 是正确的结果,但是这意味着这些比较对于使用 NaN 进行排序没有用。)
理解这种区别,即数字是精确的,运算可能是近似的,对于分析、设计和证明涉及浮点运算的算法至关重要。
当然,在一个数字数组中,数字可能包含早期操作的错误:它们与使用实数运算得到的数字不同。在这种情况下,数字将根据它们的实际计算值排序,而不是根据您希望它们具有的理想值排序。这不是 std::sort
正确排序数字的障碍。
要对包括 NaN 的数据进行排序,您需要一个全序谓词来报告一个数据是否比另一个数据在所需的排序顺序中早,例如报告 NaN 晚于任何非 NaN 的数据。 IEEE-754 定义了一个全序谓词,但我不能说它在 C++ 中的可用性。 (根据我试过的快速测试,std::less
似乎没有提供。)