微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我的问题是我们可以避免 if 条件吗?

如何解决我的问题是我们可以避免 if 条件吗?

我有如下代码条件

for(int i=0;i<Number;i++)
{     
     int* pIn = pInputArr[i];
     int* pOut = pOutputArr[i];
      
     for(int Input_number =0;Input_number<100;Input_number++)
         {
            Some_fun(pIn,pOut );
            if (Input_number % 2 == 0)
            {
               pIn = pOutputArr[i];
               pOut = pInputArr[i];
            }
            else
           {
               pOut =  pOutputArr[i];
               pIn = pInputArr[i];
           }
      }
 }    

我想用嵌入式编程中更有效的方式替换它,因为有人告诉我,嵌入式编程中的分支操作成本很高。有没有更简洁的方法来使用位操作而不使用 if 条件来实现这一点? 也不使用任何内置函数,例如 swap 等。

基于奇数和偶数条件,我正在交换作为 Some_func 中参数的缓冲区的角色。我在几个帖子中检查了类似的查询,但没有发现它们有用。任何建议将不胜感激。

解决方法

如果您想交替使用,则无需检查均匀度 - 只需交换即可。

for(int Input_number =0;Input_number<3;Input_number++)
{
    Some_fun(pIn,pOut);
    std::swap(pIn,pOut);
}
,

您需要更多的是一个公式,它接受条件值并用它做一些事情。在您的场景中,您可以使用 pInputArr[i]pOutputArr[i] 创建一个数组,然后使用条件值(0 或 1)进行分配。我也更喜欢按位与 1 而不是模检查,因为它是一个单操作表达式:

int arr = {pInputArr[i],pOutputArr[i]};
bool cond = Input_number & 1;
pIn = arr[!cond];
pOut = arr[cond];
,

为了实现无分支,您可以执行以下操作:

int isInputNumberOdd = Input_number % 2; 
pIn  = (pOutputArr[i] * isInputNumberOdd) + (pInputArr[i] * (1 - isInputNumberOdd));
pOut = (pOutputArr[i] * (1 - isInputNumberOdd)) + (pInputArr[i] * isInputNumberOdd);

您总是将一项加法乘以零,从而有效地将值设置为另一项。

,

您可以只循环 {values["guardians"].map((guardian: any,index: number) => { console.log(values["guardians"]) <--------------------------------------first console.log return ( <GuardianCard person={guardian}> <CustomTextField select label="relationship" defaultValue onChange={(e: ChangeEvent<{}>,value: any) => { const relationshipValue = value.props.value; console.log(values["guardians"]) <--------------------------------------second console.log setFieldValue(`guardians.${index}.relationship`,relationshipValue); }} fullWidth required > <MenuItem value={0}>Mother</MenuItem> <MenuItem value={1}>Father</MenuItem> <MenuItem value={2}>Grand parents</MenuItem> <MenuItem value={3}>Uncle/Aunt</MenuItem> </CustomTextField> <MyRadio name="primaryGuardian" type="radio" value={guardian.id} label="Primary" values={values["primaryGuardian"]}/> </GuardianCard> ) })} 次,然后调用该函数两次。

input_number

或者如果您的编译器无法优化上述内容以仅在每个数组中执行一次下标:

for(int i = 0; i < Number; ++i) {     
     for(int Input_number = 0; Input_number < 100 / 2; ++Input_number) {
        Some_fun(pInputArr[i],pOutputArr[i]);
        Some_fun(pOutputArr[i],pInputArr[i]);
    }
}
,

毫无疑问,您的算法可以改进,但是如果您担心分支指令,您就会为小事而烦恼 - 让编译器优化器担心这一点,并将高效算法的注意力集中在指令级优化上。

例如,您可以简单地“展开”循环:

for( int Input_number = 0;  Input_number < 100; Input_number += 2 )
{
    Some_fun(pIn,pOut );
    pIn = pOutputArr[i];
    pOut = pInputArr[i];
    
    Some_fun(pIn,pOut );
    pOut =  pOutputArr[i];
    pIn = pInputArr[i];
}

然后没有对奇数/偶数和 if-else 的测试。您无法消除计算中的分支,for 循环与函数调用一样涉及分支。然而,您可以使用更少分支的高效算法,但更重要的是消除不必要的表达式评估。

您可以进一步消除分配:

for( int Input_number = 0;  Input_number < 100; Input_number += 2 )
{
    Some_fun( pInputArr[i],pOutputArr[i] ) ;
    Some_fun( pOutputArr[i],pInputArr[i] ) ;
}

关键是在优化中有两件事要避免:

  • 过早的优化 - 花时间做一些已经足够快的事情
  • 微优化 - 担心编译器如何将您的代码转换为机器指令并对其进行二次猜测。

您可能在这里都尝试过。您应该专注于本质上高效的算法和数据结构,而将指令生成留给编译器。

,

您可以创建一个 2 元素数组来保存要交换的指针,然后将计算结果用作该数组的索引,例如:

int** pArr[2];
int *pIn,*pOut;

for(int i = 0; i < Number; ++i)
{     
    pArr[0] = &pInputArr[i];
    pArr[1] = &pOutputArr[i];

    pIn = *pArr[0];
    pOut = *pArr[1];

    for(int Input_number = 0; Input_number < 100; ++Input_number)
    {
        Some_fun(pIn,pOut);
        bool isEven = (Input_number % 2 == 0);
        pIn = *pArr[isEven];
        pOut = *pArr[!isEven];
    }
}    

或者,由于您知道计算结果将在每次循环迭代中切换,那么只需完全摆脱计算即可。例如:

int** pArr[2];
int *pIn,*pOut;
bool isEven;

for(int i = 0; i < Number; ++i)
{     
    pArr[0] = &pInputArr[i];
    pArr[1] = &pOutputArr[i];

    pIn = *pArr[0];
    pOut = *pArr[1];

    isEven = true;

    for(int Input_number = 0; Input_number < 100; ++Input_number)
    {
        Some_fun(pIn,pOut);
        pIn = *pArr[isEven];
        pOut = *pArr[!isEven];
        isEven = !isEven;
    }
}    

请注意,在上面的两个示例中,我都使用指向指针的指针来确定要传递给 Some_fun() 的每个数组元素。这是因为您的原始代码在每次迭代时都会重新索引到 pInputArr[]pOutputArr[] 数组中,并且不清楚 Some_fun() 是否可以更改这些数组在每个数组上指向的内容迭代。如果它们没有改变,那么作为 @molbdnilo suggested,你可以在每次迭代时交换本地指针,例如:

for(int i = 0; i < Number; ++i)
{     
    int *pIn = pInputArr[i];
    int *pOut = pOutputArr[i];

    for(int Input_number = 0; Input_number < 100; ++Input_number)
    {
        Some_fun(pIn,pOut);

        int *pTmp = pIn;
        pIn = pOut;
        pOut = pTmp;
    }
}    
,

如果您确定将运行 100 次,并且每个 some_fun() 都应该交替使用参数,则可以完全放弃 if 语句,

for(int Input_number = 0; Input_number < 50; Input_number++)
{
    Some_fun(pIn,pOut);
    Some_fun(pOut,pIn);
}

这样您就不需要交换两者或使用 if 语句。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。