【问题标题】:A question about function call and evaluation in C++关于 C++ 中函数调用和求值的问题
【发布时间】:2011-05-13 11:36:24
【问题描述】:

你好, 关于以下问题,我可能有一个直截了当的问题:

我有一个函数

double afunction(double *myarray)
{   
    double ret = 1.0;
    for(int i = 0; i < 4; i++)
        ret *= myarray[i]*myarray[i];
    return ret;
}

现在我想修改它,以便传递两个新参数:int index,描述要更改的 myarray 的哪个索引,如下所示:myarray[ index ] = *add;。这将是以下内容:

double afunction(double *myarray, int index, double *add)
{   
    myarray[ index ] += *add;
    double ret = 1.0;
    for(int i = 0; i < 4; i++)
        ret *= myarray[i]*myarray[i];
    return ret;
}

问题是:我不想修改数组 myrray 并且我不想为此创建一个新数组,因为内存-问候(这稍后将在 GPU 上计算,无论如何我无法在内核函数中分配一个全新的数组。 轻松解决这个问题? 谢谢!

编辑 对不起,我打错了一些东西。取而代之的是myarray[ index ] = *add; 我的意思是myarray[ index ] += *add;

EDIT2 一个更大的函数的例子,以后可以很容易地扩展到大约 50 个不同的返回案例。因此,让 if 语句修改特定值 myarray[index] 并在每个返回案例中添加 *add 非常难看:(

double afunction(double *myarray, int funcIndex, int indexAdd, double *add)
{   
    myarray[ indexAdd ] += *add;

    if(funcIndex >= 1 && funcIndex <= 4)
        return myarray[1]*myarray[1]*myarray[2];

    switch(funcIndex)
    {
        case 5:
            return sin(myarray[3]) * cos(myarray[1]);
        case 6:
            double ret = exp(myarray[1]);
            for(int i = 1; i < 5; i++)
                ret *= (myarray[ i ]-myarray[ 5-i ]);
            return ret;
        case 7:
            double ret = 0.0;
            for(int i = 1; i < 10; i++)
                ret += myarray[ i ];
            return ret;
    }

    return 0.0;
}

【问题讨论】:

    标签: c++ arrays function


    【解决方案1】:
    double ret = 1.0;
    for(int i = 0; i < 4; i++)
        if (index == i)
            ret *= (*add) * (*add);
        else
            ret *= myarray[i]*myarray[i];
    

    或:

    double ret = (*add) * (*add);
    for(int i = 0; i < 4; i++)
        ret *= myarray[i]*myarray[i];
    
    ret /= myarray[index] * myarray[index];
    

    这不是 100% 等价的,因为您使用的是浮点数。

    编辑:好的,看到您编辑了原始问题。一种可能可以接受的替代方法是:

    myarray[ indexAdd ] -= *add;
    

    在您完成其余的计算之后。同样,不能保证myarray[indexAdd] 将返回到完全它的旧值。

    或者更好的是,将旧值保存在函数顶部,然后将其恢复:

    float old = myarray[ indexAdd ];
    myarray[ indexAdd ] += *add;
    //do work
    myarray[ indexAdd ] = old;
    

    【讨论】:

    • 它可能工作正常,也可能不行,这完全取决于函数的输入。
    • 没错。而这个“取决于”让我感到害怕。
    • 虽然所有浮点函数都对输入敏感,但如果你打乱myarray 中元素的顺序,即使是原始函数(没有*add 的东西)也会返回不同的值。跨度>
    • 好的,谢谢你们。你是对的,我明白了。问题在于:这个函数可能看起来很简单,而且不像上面所说的那么简单(我插入了一个例子)。当然,我可以在每种情况下插入语句,但这看起来真的很难看。所以我打赌可能没有办法不复制数组并修改值,除了在每种情况下真正实现 if 语句来修改 ONE 值:(
    • 好的,再次感谢。我觉得最后一个解决方案是“最酷的”,因为它很容易实现,但是因为我想稍后在多线程环境中使用它,所以这也是不可能的:(
    【解决方案2】:
    double afunction(double *myarray, int index, double *add)
    {   
        double ret = (*add) * (*add);
        for(int i = 0; i < 4; i++)
            if( i != index )
                ret *= myarray[i]*myarray[i];
        return ret;
    }
    

    【讨论】:

      【解决方案3】:

      有几种可能的解决方案:

      显而易见的:

      double
      aFunction( double* array, int index, double add )
      {
          double result = 1.0;
          for ( int i = 0; i != 4; ++ i ) {
              double tmp = array[i];
              if ( i == index ) {
                  tmp += add;
              }
              result *= tmp * tmp;
          }
          return result;
      }
      

      可能更快(没有 if 在循环中),但可能不同 结果:

      double
      aFunction( double* array, int index, double add )
      {
          double result = 1.0;
          for ( int = 0; i != 4; ++ i ) {
              result *= array[i] * array[i];
          }
          //  Since we multiplied by array[i]^2, when we should
          //  have multipied by (array[i] + add)^2...
          result *= 2 * array[index] * add + add * add;
          return result;
      }
      

      我怀疑这个是否值得一试 四个元素的数组:四个ifs 可能不会比 最后的附加计算。然而,对于更长的数组,它可能是 值得考虑。

      最后,更多供参考,因为它真的很丑,而且只适用于 单线程环境:

      double
      aFunction( double* array, int index, double add )
      {
          array[index] += add;
          double result = 1.0;
          for ( int i = 0; i != 4; ++ i ) {
              result *= array[i] * array[i];
          }
          array[index] -= add;
          return result;
      }
      

      根据实际的硬件和编译器优化,这可能 是最快的。 (但同样,对于四个元素,它远非 肯定的。)

      另外两个关于代码的cmets:如果你不打算修改 array,您可能应该将其作为double const* 传递(其中 消除了上面的最后一种可能性),因为你所做的就是阅读 单个值,将add 作为指针传递确实没有意义; 在我上面的代码中,我是按值传递的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-05
        • 2021-10-29
        相关资源
        最近更新 更多