浮点数的三向比较
3-way comparison of floating-point numbers
给定一对浮点数,执行三向比较的最佳方法是什么,即 return 负数、零或正数,具体取决于第一个数字是否小于,等于或大于第二个数字?
Perl、Java 和 C++20 等一些语言内置了这个运算符,或者在标准库中。但是,我问的是如何在普通 C 中执行此操作。
如果输入是整数,编写一对双向比较将是一件简单的事情。但相比之下,由于 NaN 的特殊行为,浮点输入更加复杂。考虑到这一点,正确的做法是什么?
Returns -1、0、1 表示小于、等于和大于,加上一些其他值表示不可比较:
#include <math.h>
int cmp(double a, double b) {
if (isunordered(a, b)) {
/* at least one NaN, return whatever you feel is appropriate */
return 42;
}
return (a>b) - (a<b);
}
如果您想与 epsilon 进行模糊比较,请随意使 <
和 >
稍微复杂一些...
What's the appropriate way to do it, taking that (NAN) into account?
Return 允许 4 个不同 returns 值的 FP 类型:-1.0、0.0、1.0、NAN。
下面还有 returns -0.0 在 select 个案例中涉及 -0.0.
#include <math.h>
double fcmp(double a, double b) {
if (isunordered(a, b)) return NAN;
if (a > b) return 1.0;
if (a < b) return -1.0;
return a - b;
}
我什至会考虑传播 a
或 b
时 NAN
以维护 NAN 负载。可能存在许多不同的非 a 数。
double fcmp(double a, double b) {
if (isnan(a)) return a;
if (isnan(b)) return b;
...
}
但让我们看一下用于排序的 3 向 qsort()
。问题是将 NAN 放在哪里?一个共同的目标是将它们放在列表的最后 - 即所有 NAN 都比其他的大。为此,我们需要一致比较,即使两个操作数都是具有不同有效负载的 NAN。
// All NAN considered greater than others
// return 0, a positive or negative int.
int fcmp_for_qsort(const void *ap, const void *bp) {
double a = *(const double *) ap;
double b = *(const double *) bp;
if (isnan(a)) {
if (isnan(b)) {
return 0;
}
return 1;
}
if (isnan(b)) -1;
return (a > b) - (a < b);
}
给定一对浮点数,执行三向比较的最佳方法是什么,即 return 负数、零或正数,具体取决于第一个数字是否小于,等于或大于第二个数字?
Perl、Java 和 C++20 等一些语言内置了这个运算符,或者在标准库中。但是,我问的是如何在普通 C 中执行此操作。
如果输入是整数,编写一对双向比较将是一件简单的事情。但相比之下,由于 NaN 的特殊行为,浮点输入更加复杂。考虑到这一点,正确的做法是什么?
Returns -1、0、1 表示小于、等于和大于,加上一些其他值表示不可比较:
#include <math.h>
int cmp(double a, double b) {
if (isunordered(a, b)) {
/* at least one NaN, return whatever you feel is appropriate */
return 42;
}
return (a>b) - (a<b);
}
如果您想与 epsilon 进行模糊比较,请随意使 <
和 >
稍微复杂一些...
What's the appropriate way to do it, taking that (NAN) into account?
Return 允许 4 个不同 returns 值的 FP 类型:-1.0、0.0、1.0、NAN。
下面还有 returns -0.0 在 select 个案例中涉及 -0.0.
#include <math.h>
double fcmp(double a, double b) {
if (isunordered(a, b)) return NAN;
if (a > b) return 1.0;
if (a < b) return -1.0;
return a - b;
}
我什至会考虑传播 a
或 b
时 NAN
以维护 NAN 负载。可能存在许多不同的非 a 数。
double fcmp(double a, double b) {
if (isnan(a)) return a;
if (isnan(b)) return b;
...
}
但让我们看一下用于排序的 3 向 qsort()
。问题是将 NAN 放在哪里?一个共同的目标是将它们放在列表的最后 - 即所有 NAN 都比其他的大。为此,我们需要一致比较,即使两个操作数都是具有不同有效负载的 NAN。
// All NAN considered greater than others
// return 0, a positive or negative int.
int fcmp_for_qsort(const void *ap, const void *bp) {
double a = *(const double *) ap;
double b = *(const double *) bp;
if (isnan(a)) {
if (isnan(b)) {
return 0;
}
return 1;
}
if (isnan(b)) -1;
return (a > b) - (a < b);
}