类似于Fastest way to determine if an integer is between two integers (inclusive) with known sets of values,我想弄清楚某个值(最有可能是双精度浮点数)是否在其他两个值(相同类型)之间。需要注意的是,我尚不知道哪个值大于另一个值,因此我试图确定是否应该/如何避免使用std :: max / min。这是一些我已经尝试过测试的代码:
inline bool inRangeMult(double p, double v1, double v2) {
return (p - v1) * (p - v2) <= 0;
}
inline bool inRangeMinMax(double p, double v1, double v2) {
return p <= std::max(v1, v2) && p >= std::min(v1, v2);
}
inline bool inRangeComp(double p, double v1, double v2) {
return p < v1 != p < v2;
}
int main()
{
double a = 1e4;
std::clock_t start;
double duration;
bool res = false;
start = std::clock();
for (size_t i = 0; i < 2e4; ++i) {
for (size_t j = 0; j < 2e4; ++j) {
res = inRangeMult(a, i, j) ? res : !res;
}
}
duration = std::clock() - start;
std::cout << "InRangeMult: " << duration << std::endl;
start = std::clock();
for (size_t i = 0; i < 2e4; ++i) {
for (size_t j = 0; j < 2e4; ++j) {
res = inRangeMinMax(a, i, j) ? res : !res;
}
}
duration = std::clock() - start;
std::cout << "InRangeMinMax: " << duration << std::endl;
start = std::clock();
for (size_t i = 0; i < 2e4; ++i) {
for (size_t j = 0; j < 2e4; ++j) {
res = inRangeComp(a, i, j) ? res : !res;
}
}
duration = std::clock() - start;
std::cout << "InRangeComp: " << duration << std::endl;
std::cout << "Tricking the compiler by printing inane res: " << res << std::endl;
}
在大多数运行中,我发现使用std :: min / max仍然是最快的(最新运行分别打印346、310和324),但我不确定100%的把握是最好的测试设置,或者我已经用尽了所有合理的实现方式。
我将感谢任何人提供的更好的性能分析设置和/或更好的实现。
编辑:更新了代码,使其不易于进行编译器优化。
第二次编辑:调整了a的值和迭代次数。一次运行的结果是:
答案 0 :(得分:2)
第一次测试:
(p - v1) * (p - v2) <= 0
由于算术运算,可能导致上溢或下溢。
最后一个:
p < v1 != p < v2
没有提供与其他结果相同的结果,在边界v1
和v2
方面都包含在内。考虑到double
类型的范围和精度,这是一个公认的小差异,但这可能很重要。
另一个选择是显式扩展第二个函数的逻辑:
p <= std::max(v1, v2) && p >= std::min(v1, v2) // v1 and v2 are compared twice
变成这样:
bool inRangeComp(double p, double v1, double v2) {
return v1 <= v2 // <- v1 and v2 are compared only once
? v1 <= p && p <= v2
: v2 <= p && p <= v1;
}