【问题标题】:how could I use the power function in c/c++ without pow(), functions, or recursion如何在没有 pow()、函数或递归的情况下在 c/c++ 中使用幂函数
【发布时间】:2021-12-19 17:38:41
【问题描述】:

我正在使用 C++ 编译器,但用 C 编写代码(如果有帮助的话)

有一串数字

(-1^(a-1)/2a-1)B^(2a-1)

A 和 X 是用户定义的...A 必须是正数,但 X 可以是任何值 (+,-)...

解码这个序列...我需要使用指数/幂,但受到一些限制...我不能创建另一个函数,使用递归或pow()(以及 cmath 附带的其他高级数学函数或 math.h)。

有很多类似的问题,但很多答案都使用了与这个问题没有直接关系的函数和递归。

这是与pow() 完美配合的代码,我花了很多时间尝试修改它以用我自己的代码替换pow(),但似乎没有任何工作......主要是得到错误的结果。 X 和 J 是用户输入的变量

for (int i = 1; i < j; i++) 
    sum += (pow(-1, i - 1)) / (5 * i - 1) * (pow(x, 5 * i - 1));
}

【问题讨论】:

  • 我有一个数字序列,我需要放入 pow(), - 这是什么意思?你到底需要做什么?
  • 一个简单的for 循环应该可以工作。
  • @JohnnyMopp 除非是分数幂:P
  • 好吧,pow(-1, i - 1) 是微不足道的。 -1 奇数幂是-1,偶数幂是1
  • 如果指数是整数,您可以使用二进制取幂算法(平方取幂),如果指数为负数,则结合倒数运算。但是由于指数每次迭代都会增加一个常数,所以这个算法是多余的。

标签: c++ c math pow exponent


【解决方案1】:

您可以使用来摆脱无函数调用的限制,因为宏会生成从技术上讲不是函数调用的内联代码

但是在更复杂的操作宏不能有返回值的情况下,所以你需要为结果使用一些局部变量(如果有多个表达式),例如:

int ret;
#define my_pow_notemp(a,b) (b==0)?1:(b==1)?a:(b==2)?a*a:(b==3)?a*a*a:0
#define my_pow(a,b)\
    {\
    ret=1;\
    if (int(b& 1)) ret*=a;\
    if (int(b& 2)) ret*=a*a;\
    if (int(b& 4)) ret*=a*a*a*a;\
    if (int(b& 8)) ret*=a*a*a*a*a*a*a*a;\
    if (int(b&16)) ret*=a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a;\
    if (int(b&32)) ret*=a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a;\
    }
void main()
   {
   int a=2,b=3,c;
   c=my_pow_notemp(a,b); // c = a^b
   my_pow(a,b); c = ret; // c = a^b
   }

如您所见,您可以直接使用my_pow_notemp,但代码是硬编码的,因此只有a^3,如果您想要更多,您必须将其添加到代码中。 my_pow 接受最大为 a^63 的指数,它也是一个示例,说明如何在宏内部代码更复杂的情况下返回值。如果您需要非整数或负指数,这里有一些(常规)方法来计算幂(但是如果没有循环/递归,将其转换为展开代码将非常困难):

如果您想摆脱递归和函数调用,您可以使用 模板 代替宏,但这仅限于 C++。

template<class T> T my_pow(T a,T b)
    {
    if (b==0) return 1;
    if (b==1) return a;
    return a*my_pow(a,b-1);
    }
void main()
   {
   int a=2,b=3,c;
   c=my_pow(a,b);
   }

正如您所见,模板具有返回值,因此即使使用更复杂的代码(不止一个表达式)也没有问题。

避免循环,您可以使用 LUT 表格

int my_pow[4][4]=
    {
    {1,0,0,0},  // 0^
    {1,1,1,1},  // 1^
    {1,2,4,8},  // 2^
    {1,3,9,27}, // 3^
    };
void main()
   {
   int a=2,b=3,c;
   c=my_pow[a][b];
   }

如果您可以访问 FPU 或高级数学汇编,则可以使用它,因为 asm 指令不是函数调用。 FPU 通常具有原生的log,exp,pow 函数。然而,这将代码限制在特定的指令集!!!

这里有一些例子:

所以当我考虑到您的限制时,我认为最好的方法是:

#define my_pow(a,b) (b==0)?1:(b==1)?a:(b==2)?a*a:(b==3)?a*a*a:0
void main()
   {
   int a=2,b=3,c;
   c=my_pow(a,b); // c = a^b
   }

这将适用于 int 指数 b 最多 3(如果您想要更多,只需添加 (b==4)?a*a*a*a: ... :0)以及 intfloat 基础 a。如果您需要更大的指数,请使用带有局部临时变量的复杂版本来返回结果。

[Edit1] 终极单一表达式宏,通过平方高达 a^15

#define my_pow(a,b) (1* (int(b&1))?a:1* (int(b&2))?a*a:1* (int(b&4))?a*a*a*a:1* (int(b&8))?a*a*a*a*a*a*a*a:1)
void main()
   {
   int a=2,b=3,c;
   c=my_pow(a,b); // c = a^b
   }

如果您想要超过a^15,只需为每一位指数添加子项(int(b&amp;16))?a*a*a*a*a*a*a*a*a*a*a*a*a*a*a*a:1 等等。

【讨论】:

    【解决方案2】:

    这是一个系列。根据之前的迭代替换pow()@Bathsheba

    代码不需要调用pow()。它可以形成pow(x, 5 * i - 1)pow(-1, i - 1),因为两者都有一个基于迭代器iint 指数,来自先前的循环迭代。

    示例:
    f(x, i) = pow(x, 5 * i - 1)
    然后f(x, 1) = x*x*x*x
    f(x, i &gt; 1) = f(x, i-1) * x*x*x*x*x

    double power_n1 = 1.0; 
    double power_x5 = x*x*x*x; 
    for (int i = 1; i < j + 1; i++) 
      // sum += (pow(-1, i - 1)) / (5 * i - 1) * (pow(x, 5 * i - 1));
      sum += power_n1 / (5 * i - 1) * power_x5;
      power_n1 = -power_n1;
      power_x5 *= x*x*x*x*x; 
    }
    

    【讨论】:

      猜你喜欢
      • 2018-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-09-14
      • 2022-01-16
      相关资源
      最近更新 更多