程序员面试题精选100题(44)-数值的整数次方

程序员面试题精选100题(44)-数值的整数次方
题目:实现函数double Power(double base, int exponent),求baseexponent次方。不需要考虑溢出。
方法一:
由于输入的exponent是个int型的数值,因此可能为正数,也可能是负数。
见下面代码:
bool g_InvalidInput=false;
double Power(double base,int exponent)
{
  g_InvalidInput=false;
  if(base==0&&exponent<0)
  {
    g_InvalidInput=true;
return 0.0;
  }
  unsigned int unsignedExponent=static_cast<unsigned int>(exponent);
  if(exponent<0)
     unsigned int unsignedExponent=static_cast<unsigned int>(-exponent);
  double result=PowerWithUnsignedExponent(base,unsignedExponent);
  if(exponent<0)
 result=1.0/result;
  return result;
}
double PowerWithUnsignedExponent(double base,unsigned int exponent)
{
  double result=1.0;
  for(int i=1;i<=exponent;i++)
 result*=base;
  return result;
}
方法二:

如果我们输入的指数exponent32,按照前面的算法,我们在函数PowerWithUnsignedExponent中的循环中至少需要做乘法31次。但我们可以换一种思路考虑:我们要求出一个数字的32次方,如果我们已经知道了它的16次方,那么只要在16次方的基础上再平方一次就可以了。而16次方是8次方的平方。这样以此类推,我们求32次方只需要做5次乘法:求平方,在平方的基础上求4次方,在4次方的基础上平方求8次方,在8次方的基础上求16次方,最后在16次方的基础上求32次方。

32刚好是2的整数次方。如果不巧输入的指数exponent不是2的整数次方,我们又该怎么办呢?我们换个数字6来分析,6就不是2的整数次方。但我们注意到6是等于2+4,因此我们可以把一个数的6次方表示为该数的平方乘以它的4次方。于是,求一个数的6次方需要3次乘法:第一次求平方,第二次在平方的基础上求4次方,最后一次把平方的结果和4次方的结果相乘。

现在把上面的思路总结一下:把指数分解了一个或若干个2的整数次方。我们可以用连续平方的方法得到以2的整数次方为指数的值,接下来再把每个前面得到的值相乘就得到了最后的结果。

到目前为止,我们还剩下一个问题:如何将指数分解为一个或若干个2的整数次方。我们把指数表示为二进制数再来分析。比如6的二进制表示为110,在它的第2位和第3位为1,因此6=2^(2-1)+2^(3-1) 。也就是说只要它的第n位为1,我们就加上2n-1次方。

最后,我们根据上面的思路,重写函数PowerWithUnsignedExponent

代码为:
double PowerWithUnsignedExponent(double base,unsigned int exponent)
{
std::bitset<32> bits(exponent);
if(bits.none())
return 1.0;
int numberOf1=bits.count();
    double multiplication[32];
for(int i=0;i<32;i++)
{
multiplication[i]=1.0;
}
int count=0;
double power=1.0;
    for(int i=0;i<32&&count<numberOf1;i++)
{
 if(i==0)
 power=base;
 else
 power=power*power;
 if(bits.at(i))
 {
   multiplication[i]=power;
 }
}
power=1.0;
for(int i=0;i<32;i++)
{
 if(bits.at(i))
 power*=multiplication[i];
}
return power;
}
在上述代码中,我们用C++的标准函数库中bitset把整数表示为它的二进制,增大代码的可读性。如果exponent的第i位为1,那么在数组multiplication的第i个数字中保存以base为底数,以2i次方为指数的值。最后,我们再把所以位为1在数组中的对应的值相乘得到最后的结果。
方法三:

上面的代码需要我们根据base的二进制表达的每一位来确定是不是需要做乘法。对二进制的操作很多人都不是很熟悉,因此编码可能觉得有些难度。我们可以换一种思路考虑:我们要求出一个数字的32次方,如果我们已经知道了它的16次方,那么只要在16次方的基础上再平方一次就可以了。而16次方是8次方的平方。这样以此类推,我们求32次方只需要做5次乘法:先求平方,在平方的基础上求4次方,在4次方的基础上平方求8次方,在8次方的基础上求16次方,最后在16次方的基础上求32次方。

也就是说,我们可以用如下公式求an次方:

程序员面试题精选100题(44)-数值的整数次方 - 何海涛 - 微软、Google等面试题

这个公式很容易就能用递归来实现。新的PowerWithUnsignedExponent代码如下:

double PowerWithUnsignedExponent(double base,unsigned int exponent)
{
  if(exponent==0)
 return 1;
  if(exponent==1)
 return base;
  double result=PowerWithUnsignedExponent(base,exponent>>1);
  result*=result;
  if(exponent&0x1==1)
 result*=base;
  return result;
}

参考:<<剑指offer名企面试官精讲典型编程题>>-----何海涛
资源下载链接为: https://pan.quark.cn/s/67c535f75d4c 在机器人技术中,轨迹规划是实现机器人从一个位置平稳高效移动到另一个位置的核心环节。本资源提供了一套基于 MATLAB 的机器人轨迹规划程序,涵盖了关节空间和笛卡尔空间两种规划式。MATLAB 是一种强大的数值计算与可视化工具,凭借其灵活易用的特点,常被用于机器人控制算法的开发与仿真。 关节空间轨迹规划主要关注机器人各关节角度的变化,生成从初始配置到目标配置的连续路径。其关键知识点包括: 关节变量:指机器人各关节的旋转角度或伸缩长度。 运动学逆解:通过数学法从末端执行器的目标位置反推关节变量。 路径平滑:确保关节变量轨迹连续且无抖动,常用法有 S 型曲线拟合、多项式插值等。 速度和加速度限制:考虑关节的实际物理限制,确保轨迹在允许的动态范围内。 碰撞避免:在规划过程中避免关节与其他物体发生碰撞。 笛卡尔空间轨迹规划直接处理机器人末端执行器在工作空间中的位置和姿态变化,涉及以下内容: 工作空间:机器人可到达的所有三维空间点的集合。 路径规划:在工作空间中找到一条从起点到终点的无碰撞路径。 障碍物表示:采用二维或三维网格、Voronoi 图、Octree 等数据结构表示工作空间中的障碍物。 轨迹生成:通过样条曲线、直线插值等法生成平滑路径。 实时更新:在规划过程中实时检测并避开新出现的障碍物。 在 MATLAB 中实现上述规划法,可以借助其内置函数和工具箱: 优化工具箱:用于解决运动学逆解和路径规划中的优化问。 Simulink:可视化建模环境,适合构建和仿真复杂的控制系统。 ODE 求解器:如 ode45,用于求解机器人动力学程和轨迹执行过程中的运动学问。 在实际应用中,通常会结合关节空间和笛卡尔空间的规划法。先在关节空间生成平滑轨迹,再通过运动学正解将关节轨迹转换为笛卡
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值