函数到 return 中位数 3
Function to return median of 3
我正在寻找找到中位数 3 的最佳解决方案。我希望它的行数尽可能少。提前谢谢你:)我试过这样的东西:
int median(int a, int b, int c)
{
if ((a >= b && a <= c) || (a <= b && a >= c)) return a;
if ((b >= a && b <= c) || (b <= a && b >= c)) return b;
return c;
}
我认为这个解决方案没问题,但也许还有更好的方法?
列举所有的可能性当然是一种方法。
但我们也可以进行比较——毕竟 a < b 的结果已经告诉你这两者的相对顺序。
int median3(int a, int b, int c) {
// Sort a and b
int lo, hi;
if (a <= b) {
lo = a;
hi = b;
} else {
lo = b;
hi = a;
}
// Check where c lies relative to hi & lo
if (c > hi) {
return hi;
} else if (c < lo) {
return lo;
} else {
return c;
}
}
是否认为这个“更好”(或更具可读性)可能是一个品味问题。
怎么样
int median(int a, int b, int c) {
std::vector<int> result = { a,b,c };
std::sort(result.begin(), result.end());
return result[1];
}
int median(int a, int b, int c)
{
return ((b > a) == (a > c)) ? a : ((a > b) == (b > c)) ? b : c;
}
https://godbolt.org/z/4G3dzPcs3
以上代码有小错误(证明测试很重要),这里是修复版本:
int median(int a, int b, int c)
{
return (b > a) == (a > c) ? a : (b > a) != (b > c) ? b : c;
}
https://godbolt.org/z/8bq38hvaj(包含早期代码中的测试用例修复错误)。
int getMedian(int a, int b , int c) {
int p = a-b,q=b-c,r=a-c;
if(p*q > 0) return b;
return p*r > 0?c:a;
}
这样就可以了
短篇读起来可能很晦涩:
return a < b ? c < a ? a : b < c ? b : c : c < b ? b : a < c ? a : c;
我可以添加多余的括号来澄清,但不确定它是否澄清了什么:
return a < b ? (c < a ? a : b < c ? b : c) : c < b ? b : a < c ? a : c;
这应该适用于所有平台 int
值,并支持重复(例如,两个或所有三个参数相等的情况)。
int median(int a, int b, int c)
{
return ((a > b) ^ (a > c)) ? a : ((b < a) ^ (b < c)) ? b : c;
}
O2 优化 asm 示例:
clang 12.0.1
median:
mov eax, edx
cmp edi, esi
setg r8b
cmp edi, edx
setg dl
xor dl, r8b
cmp esi, eax
setl cl
xor cl, r8b
cmovne eax, esi
test dl, dl
cmovne eax, edi
ret
gcc 11.2
median:
cmp edi, esi
mov eax, edi
setg cl
cmp edi, edx
setg dil
cmp cl, dil
je .L5
ret
.L5:
cmp esi, edx
setl al
cmp cl, al
mov eax, edx
cmovne eax, esi
ret
首先google搜索:
https://www.geeksforgeeks.org/middle-of-three-using-minimum-comparisons/
经过更多搜索后发现:
Fastest way of finding the middle value of a triple?
median = max(min(a,b), min(max(a,b),c));
最好的实施显然是一个品味问题。
如果可能,我更喜欢操作布尔表达式,并限制比较次数。
#include <iostream>
int median (int a, int b, int c) {
auto tab = (a < b), tac = (a < c), tbc = (b < c);
if (tab xor tac) return a;
if (!tab xor tbc) return b;
return c;
}
int main() {
std::cout << median (1, 2, 3) << std::endl;
std::cout << median (1, 3, 2) << std::endl;
std::cout << median (2, 1, 3) << std::endl;
std::cout << median (2, 3, 1) << std::endl;
std::cout << median (3, 2, 1) << std::endl;
std::cout << median (3, 1, 2) << std::endl;
std::cout << median (1, 2, 2) << std::endl;
std::cout << median (2, 2, 3) << std::endl;
std::cout << median (2, 2, 1) << std::endl;
return 0;
}
我正在寻找找到中位数 3 的最佳解决方案。我希望它的行数尽可能少。提前谢谢你:)我试过这样的东西:
int median(int a, int b, int c)
{
if ((a >= b && a <= c) || (a <= b && a >= c)) return a;
if ((b >= a && b <= c) || (b <= a && b >= c)) return b;
return c;
}
我认为这个解决方案没问题,但也许还有更好的方法?
列举所有的可能性当然是一种方法。 但我们也可以进行比较——毕竟 a < b 的结果已经告诉你这两者的相对顺序。
int median3(int a, int b, int c) {
// Sort a and b
int lo, hi;
if (a <= b) {
lo = a;
hi = b;
} else {
lo = b;
hi = a;
}
// Check where c lies relative to hi & lo
if (c > hi) {
return hi;
} else if (c < lo) {
return lo;
} else {
return c;
}
}
是否认为这个“更好”(或更具可读性)可能是一个品味问题。
怎么样
int median(int a, int b, int c) {
std::vector<int> result = { a,b,c };
std::sort(result.begin(), result.end());
return result[1];
}
int median(int a, int b, int c)
{
return ((b > a) == (a > c)) ? a : ((a > b) == (b > c)) ? b : c;
}
https://godbolt.org/z/4G3dzPcs3
以上代码有小错误(证明测试很重要),这里是修复版本:
int median(int a, int b, int c)
{
return (b > a) == (a > c) ? a : (b > a) != (b > c) ? b : c;
}
https://godbolt.org/z/8bq38hvaj(包含早期代码中的测试用例修复错误)。
int getMedian(int a, int b , int c) {
int p = a-b,q=b-c,r=a-c;
if(p*q > 0) return b;
return p*r > 0?c:a;
}
这样就可以了
短篇读起来可能很晦涩:
return a < b ? c < a ? a : b < c ? b : c : c < b ? b : a < c ? a : c;
我可以添加多余的括号来澄清,但不确定它是否澄清了什么:
return a < b ? (c < a ? a : b < c ? b : c) : c < b ? b : a < c ? a : c;
这应该适用于所有平台 int
值,并支持重复(例如,两个或所有三个参数相等的情况)。
int median(int a, int b, int c)
{
return ((a > b) ^ (a > c)) ? a : ((b < a) ^ (b < c)) ? b : c;
}
O2 优化 asm 示例:
clang 12.0.1
median:
mov eax, edx
cmp edi, esi
setg r8b
cmp edi, edx
setg dl
xor dl, r8b
cmp esi, eax
setl cl
xor cl, r8b
cmovne eax, esi
test dl, dl
cmovne eax, edi
ret
gcc 11.2
median:
cmp edi, esi
mov eax, edi
setg cl
cmp edi, edx
setg dil
cmp cl, dil
je .L5
ret
.L5:
cmp esi, edx
setl al
cmp cl, al
mov eax, edx
cmovne eax, esi
ret
首先google搜索: https://www.geeksforgeeks.org/middle-of-three-using-minimum-comparisons/
经过更多搜索后发现: Fastest way of finding the middle value of a triple?
median = max(min(a,b), min(max(a,b),c));
最好的实施显然是一个品味问题。
如果可能,我更喜欢操作布尔表达式,并限制比较次数。
#include <iostream>
int median (int a, int b, int c) {
auto tab = (a < b), tac = (a < c), tbc = (b < c);
if (tab xor tac) return a;
if (!tab xor tbc) return b;
return c;
}
int main() {
std::cout << median (1, 2, 3) << std::endl;
std::cout << median (1, 3, 2) << std::endl;
std::cout << median (2, 1, 3) << std::endl;
std::cout << median (2, 3, 1) << std::endl;
std::cout << median (3, 2, 1) << std::endl;
std::cout << median (3, 1, 2) << std::endl;
std::cout << median (1, 2, 2) << std::endl;
std::cout << median (2, 2, 3) << std::endl;
std::cout << median (2, 2, 1) << std::endl;
return 0;
}