函数到 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;
}