在 c++ 中将值转换为范围内的值,使用 boost 或 std 进行优化

Posted

技术标签:

【中文标题】在 c++ 中将值转换为范围内的值,使用 boost 或 std 进行优化【英文标题】:Convert values to values inside a range in c++ , optimized using boost or std 【发布时间】:2014-07-16 01:19:28 【问题描述】:

我想验证一个数组的所有元素。如果一个元素低于一个值,则交换一个最小值,如果它高于一个值,则交换一个最大值。

但我不知道如何优化它。为此,我逐个元素地遍历所有元素,但它没有优化,并且它在非常大的数组中花费了大量的 CPU 时间。

这是我的代码示例:

#include <iostream> 
#include <math.h>
const int MAX = 10;
int main ()

    float minVal = 2.0;
    float maxVal = 11.0;

    float vElem[] = -111111.0/0.0, 10.0, 90.0, 8.0, -7.0,
                    -0.6, 5.0, 4.0, 33.0, 222222222.0/0;

    for(int i=0; i<MAX; i++)
            if(isinf(vElem[i])==-1 || vElem[i]<minVal) vElem[i] = minVal;
            if(isinf(vElem[i])==1 || vElem[i]>maxVal || isnan(vElem[i])) vElem[i] = maxVal;

            std::cout << vElem[i]<< std::endl;
    

【问题讨论】:

我没有看到任何其他选项...您必须检查每个元素并根据您的逻辑决定要做什么。即使有一个花哨的 C++ 结构,它也会下划线做同样的事情(遍历所有元素并对其执行检查操作) 如果您有多个内核,您可以使用 OpenMP 或其他方式使用自动并行化。包括标题并将#pragma omp parallel for放在循环上方 您可以访问哪个版本的 C++? (即,C++11 好吗?) 您的用例真的需要 I/O 吗?因为 I/O 开销胜过您在循环中所做的所有事情 Most efficient/elegant way to clip a number?的可能重复 【参考方案1】:

我认为在这里使用复杂的构造不会给你带来太多好处。也许让你的代码更干净一点?

std::for_each(std::begin(vElem), std::end(vElem), [](float &val) 
    val = clamp(val, minVal, maxVal);
);

this 是典型的钳位函数返回的内容

【讨论】:

您说“精巧的构造不会 [不会] 给您买太多”,但您的代码比 OP 的代码大大干净(尽管 std::transform 比 @987654324 更合适@)。 @KonradRudolph 是的,我指的是使用过滤提升范围等。没有使用transform 来避免指定result 迭代器;我同意它会清楚地传达意图 result 迭代器只是 std::begin(vElem): std::transform 可以就地工作。 这是个好主意,如果它不能t be optimize. I have g++ version 4.1.2, so I couldnt 使用它,但我已经按照你的建议重写了它。我用过for_each,虽然我没有在我的项目中安装这个boost包,但我用过std::min(std::max(val, minVal), maxVal)而且更清楚 @user3480234 更新你的 GCC,它可悲过时了。【参考方案2】:
  for(int i=0; i<MAX; i++)
      float c = vElem[i];

      //Could convert c to an integer here, so the below uses integer operations
      //Additional cost is two multiplications (scaling up and scaling back down).

      float n = c + ((c < min) * (min - c)) + ((c > max) * (max - c));
      std::cout << n << std::endl;
  
两次乘法 四个补充 两个比较

我认为这比其他答案中提到的任何clamp() 实现都快。

【讨论】:

与整数类型的运算相比,浮点运算(四次加法,两次乘法,甚至两次比较)的成本很高。 clamp() 函数只有两次比较,条件跳转。我的猜测是clamp() 函数更快。无论如何,没有板凳就无法知道。 链接到的答案是:return n = 上?上:n;这是三元运算符,表示条件分支。如果您从不需要分支 - 可能会更快,但如果您这样做了,性能成本将会非常高。 您可以在开始时将浮点数转换为整数,使用整数算术,然后将整数缩放回浮点数。

以上是关于在 c++ 中将值转换为范围内的值,使用 boost 或 std 进行优化的主要内容,如果未能解决你的问题,请参考以下文章

将一个范围内的数字转换为另一个范围内的数字[重复]

在 C++ 中将字符转换为整数

在插入触发器中将范围值解析为逗号分隔的值数组

如何使用 stringstream 在 C++ 中将字符串转换为双精度值 [关闭]

是否可以在 C++ 中将 bitset<8> 转换为 char?

如何在角度 2 中将输入值转换为大写(传递给 ngControl 的值)