钳制真实(固定/浮点)值的最快方法? [英] Fastest way to clamp a real (fixed/floating point) value?

查看:20
本文介绍了钳制真实(固定/浮点)值的最快方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有比使用 if 语句或三元运算符更有效的方法来限制实数?我想为双打和 32 位定点实现 (16.16) 执行此操作.我不是要求可以处理这两种情况的代码;它们将在单独的函数中处理.

Is there a more efficient way to clamp real numbers than using if statements or ternary operators? I want to do this both for doubles and for a 32-bit fixpoint implementation (16.16). I'm not asking for code that can handle both cases; they will be handled in separate functions.

显然,我可以这样做:

double clampedA;
double a = calculate();
clampedA = a > MY_MAX ? MY_MAX : a;
clampedA = a < MY_MIN ? MY_MIN : a;

double a = calculate();
double clampedA = a;
if(clampedA > MY_MAX)
    clampedA = MY_MAX;
else if(clampedA < MY_MIN)
    clampedA = MY_MIN;

固定点版本将使用函数/宏进行比较.

The fixpoint version would use functions/macros for comparisons.

这是在代码的性能关键部分完成的,所以我正在寻找一种尽可能有效的方法来做到这一点(我怀疑这会涉及位操作)

This is done in a performance-critical part of the code, so I'm looking for an as efficient way to do it as possible (which I suspect would involve bit-manipulation)

它必须是标准/可移植的 C,平台特定的功能在这里没有任何意义.此外,MY_MINMY_MAX 与我想要限制的值的类型相同(在上面的示例中为双精度值).

It has to be standard/portable C, platform-specific functionality is not of any interest here. Also, MY_MIN and MY_MAX are the same type as the value I want clamped (doubles in the examples above).

推荐答案

对于 16.16 表示,简单的三进制不太可能在速度方面得到改善.

For the 16.16 representation, the simple ternary is unlikely to be bettered speed-wise.

对于双打,因为您需要标准/便携式 C,所以任何类型的位摆弄都会以糟糕的方式结束.

And for doubles, because you need it standard/portable C, bit-fiddling of any kind will end badly.

即使可能有一些小技巧(我对此表示怀疑),你也会依赖双精度的二进制表示.这(及其大小)取决于实施.

Even if a bit-fiddle was possible (which I doubt), you'd be relying on the binary representation of doubles. THIS (and their size) IS IMPLEMENTATION-DEPENDENT.

您可能可以使用 sizeof(double) 来猜测"这一点,然后将各种 double 值的布局与其常见的二进制表示形式进行比较,但我认为您对此一无所知.

Possibly you could "guess" this using sizeof(double) and then comparing the layout of various double values against their common binary representations, but I think you're on a hiding to nothing.

最好的规则是告诉编译器你想要什么(即三元),然后让它为你优化.

The best rule is TELL THE COMPILER WHAT YOU WANT (ie ternary), and let it optimise for you.

谦虚的馅饼时间.我刚刚测试了 quinmars 的想法(如下),它可以工作 - 如果你有 IEEE-754 浮点数.这给下面的代码带来了大约 20% 的加速.IObviously 不可移植,但我认为可能有一种标准化的方式来询问您的编译器是否使用带有#IF 的 IEEE754 浮点格式...?

Humble pie time. I just tested quinmars idea (below), and it works - if you have IEEE-754 floats. This gave a speedup of about 20% on the code below. IObviously non-portable, but I think there may be a standardised way of asking your compiler if it uses IEEE754 float formats with a #IF...?

  double FMIN = 3.13;
  double FMAX = 300.44;

  double FVAL[10] = {-100, 0.23, 1.24, 3.00, 3.5, 30.5, 50 ,100.22 ,200.22, 30000};
  uint64  Lfmin = *(uint64 *)&FMIN;
  uint64  Lfmax = *(uint64 *)&FMAX;

    DWORD start = GetTickCount();

    for (int j=0; j<10000000; ++j)
    {
        uint64 * pfvalue = (uint64 *)&FVAL[0];
        for (int i=0; i<10; ++i)
            *pfvalue++ = (*pfvalue < Lfmin) ? Lfmin : (*pfvalue > Lfmax) ? Lfmax : *pfvalue;
    }

    volatile DWORD hacktime = GetTickCount() - start;

    for (int j=0; j<10000000; ++j)
    {
        double * pfvalue = &FVAL[0];
        for (int i=0; i<10; ++i)
            *pfvalue++ = (*pfvalue < FMIN) ? FMIN : (*pfvalue > FMAX) ? FMAX : *pfvalue;
    }

    volatile DWORD normaltime = GetTickCount() - (start + hacktime);

这篇关于钳制真实(固定/浮点)值的最快方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆