就地夹紧/剪裁数字的最佳实践

问题描述

在这里发现了两个关于在 C/C++ 中快速和/或优雅地夹紧数字的问题。 C 语言侧重于(可能是特定于平台的)优化:

Fastest way to clamp a real (fixed/floating point) value?

C++ 也与 C 相关:

Most efficient/elegant way to clip a number?

然而,这些都没有提到它是否与就地操作有关,这对我来说似乎是一条至关重要的信息。这个问题是关于就地操作的。不同的是,如果数字在范围内,则不需要进行写操作。

在浏览有关钳位的一般答案时,大多数人只是建议使用三元变体,无论如何。我想知道为什么会这样?在速度和可读性方面,我都不清楚,尤其是就地情况。我想了解是否有最佳做法,如果有,我会对理由感兴趣。

在我的示例代码中,有三个变体: 激活的变体 (1) 是我通常的实现方式。变体 (2) 使用 else if,变体 (3) 使用三元运算符。

根据对具有 -O3 的某些 i5 cpu 和 gcc 的测量,对于 TYPEfloatdouble,(1) 是最快的,(2) 和(3) 显然较慢,并且彼此相比达到大致相同的速度。对于 int,所有变体都达到大致相同的速度。

我明确地将这个问题标记为 C 而不是 C/C++,因为在后一种情况下 - 除了重复之外 - 人们会回答使用 std::clamp 或 Boost,这不是这个问题的想法。这是关于在速度和可读性方面的独立于平台的程序集免费实现的最佳实践

旁注,即使 C++:使用 std::clamp 始终与最慢的变体相当。然而,很明显,这样的函数无法针对就地操作的特定情况进行优化,内联在这里也无济于事,因为它不会改变使用的指令。

#include <stdio.h>
#include <stdlib.h>

#define MY_MAX(a,b) (((a) > (b)) ? (a) : (b))
#define MY_MIN(a,b) (((a) < (b)) ? (a) : (b))

typedef float TYPE;

int main()
{
    const TYPE a = (TYPE) (rand() % 100);
    const TYPE b = a + (TYPE) (1 + rand() % 100);

    double sum = 0.0;

    for (unsigned int i = 0; i < 100000000; i++) {
        TYPE x = (TYPE) (rand() % 100);

#if 1
        if (x < a) x = a;        
        if (x > b) x = b;
#elif 0
        if (x < a) x = a;
        else if (x > b) x = b;
#elif 0
        x = MY_MAX(a,MY_MIN(b,x));
#endif

        sum += x;
    }

    printf("%lf\n",sum);

    return 0;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)