STL系列之七 快速计算x的n次幂 power 的实现

计算x的n次幂最简单直接的方法就是相乘n次,很容易写出程序:

//计算x^n 直接乘n次 by MoreWindows( http://blog.csdn.net/MoreWindows )
int power1(int x, unsigned int n)
{
	int result = 1;
	while (n--)
		result *= x;
	return result;
}

这种计算的效率显然不高,我们可以用二分法来加速计算x^n=x^(n/2)* x^(n/2)即x^10=x^5*x^5,这种计算N次幂只要相乘O(logN)次。运用递归的方法不难写出:

//计算x^n 二分递归实现  by MoreWindows( http://blog.csdn.net/MoreWindows )
int power2(int x, unsigned int n)
{
	if (n == 0)
		return 1;
	else if (n == 1)
		return x;
	else
	{
		if (n % 2 == 1)
			return power2(x, n / 2) * power2(x, n / 2) * x;
		else
			return power2(x, n / 2) * power2(x, n / 2);
	}
}

递归毕竟比较浪费时间,且会有很多重复计算。

因此最好能换成非递归的方式来实现二分法。

考虑x^23,可以先从x ->x^2 -> x^4 -> x^8 -> x^16 取result1 = x^16,然后23-16=7。

我们只要计算x^7再与result1相乘就可以得到x^23。对于x^7也可以采用这种方法

取result2 = x^4,然后7-4=3,只要计算x^3再与result2相乘就可以得到x^7。由此可以将x^23写成x^16 * x^4* x^2 * x,即23=16+4+2+1,而23 = 10111(二进制),所以只要将n化为二进制并由低位到高位依次判断如果第i位为1,则result *=x^(2^i)。

函数实现如下:

//计算x^n   by MoreWindows( http://blog.csdn.net/MoreWindows )
int power3(int x, unsigned int n)
{
	if (n == 0)
		return 1;
	int result = 1;
	while (n != 0)
	{
		if ((n & 1) != 0)
			result *= x;
		x *= x;
		n >>= 1;
	}
	return result;
}

此函数可以在相乘O(logN)次内计算x的n次幂,且避免了重复计算。但还可以作进一步的优化,如像48=110000(二进制)这种低位有很多0的数,可以先过滤掉低位的0再进行计算,这样也会提高一些效率。程序如下:

//计算x^n  by MoreWindows( http://blog.csdn.net/MoreWindows )
int power4(int x, unsigned int n)
{
	if (n == 0)
	{
		return 1;
	}
	else
	{
		while ((n & 1) == 0)
		{
			n >>= 1;
			x *= x;
		}
	}
	int result = x;
	n >>= 1;
	while (n != 0)
	{
		x *= x;
		if ((n & 1) != 0)
			result *= x;
		n >>= 1;
	}
	return result;
}

验证一下

int main()
{
	printf("验证power4()  -- by MoreWindows( http://blog.csdn.net/MoreWindows ) --\n\n");
	for (int i = 0; i <= 10; i++)
		printf("2的%d次方为\t%d\n", i, power4(2, i));
	return 0;
}

结果为

看到这里,理解STL的power()函数应该就是个水到渠成的事情了——我们自己写的power4()正是STL的power()函数。

注,非常感谢网友evaxiao帮我找出了power4()的一个错误,我已经在文中改正了,谢谢网友evaxiao。

转载请标明出处,原文地址:http://blog.csdn.net/morewindows/article/details/7174143

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://www.cnblogs.com/captainbed

原文地址:https://www.cnblogs.com/heishanglaoyao/p/10240940.html

时间: 2024-07-31 04:55:44

STL系列之七 快速计算x的n次幂 power 的实现的相关文章

白话经典算法系列之七 堆与堆排序

堆排序与高速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先解说下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是全然二叉树或者是近似全然二叉树. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)不论什么一个子节点的键值. 2.每一个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆). 当父结点的键值总是大于或等于不论什么一个子节点的键值时为最大堆.当父结点的键值总是小于或等于不论什么一个子节点的键值时为最小堆.下图展示一个最小堆

白话经典算法系列之七 堆与堆排序(转)

堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是完全二叉树或者是近似完全二叉树. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值. 2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆). 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆.当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆.下图展示一个最小堆: 由于其它几

【转】白话经典算法系列之七 堆与堆排序

堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法.学习堆排序前,先讲解下什么是数据结构中的二叉堆. 二叉堆的定义 二叉堆是完全二叉树或者是近似完全二叉树. 二叉堆满足二个特性: 1.父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值. 2.每个结点的左子树和右子树都是一个二叉堆(都是最大堆或最小堆). 当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆.当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆.下图展示一个最小堆: 由于其它几

如何在App中实现朋友圈功能之七快速实现上拉加载朋友圈功能——箭扣科技Arrownock

如何在App中实现朋友圈功能 之七 快速实现上拉加载朋友圈功能 逻辑分析: 取出缓存postList里的最后一条数据postList a. 如果lastPost存在,说明缓存里有数据,接着取出数据库中与lastPost时间最接近的一条latestPost,以它们的created_at作为关键查询条件,去服务器取limit条(比如10)数据: 1. 如果服务器返回的Post数量大于0,将Post存入数据库,之后需要做两个查询动作: 查询出新的Like和Comment:根据本地数据库里的最新一条Li

如何在App中实现IM功能之七快速实现聊天列表排序模块——箭扣科技Arrownock

如何在App中实现IM功能 之七 快速实现聊天列表排序模块 一台设备由于用户的使用习惯差异,可能导致设备的时间和实际收发消息的时间不同,这里与大家分享利用anIM收发消息时,如何根据数据中的msgId和timestamp来进行排序. 实现逻辑 发消息时,我们需要调用anIM的sendMessage方法(同类方法还有sendBinary, sendMessageToTopic等等),这个方法有一个返回数据为messageId,即当前这一条聊天消息的唯一标识,我们需要将这个messageId保存下来

STL系列十一 随机三趣题——随机重排,文件中随机取一行,生成N个随机数

本文将介绍三个有趣的随机问题,分别是随机重新排列.从文件中随机取一行数据.生成N个随机数. 一.随机重新排列 将一个序列打乱并对其进行随机的重新排列,关键在于每种序列的被选择概率要一样,不然有失"公平".现在让我们来寻找如何保证每种序列被选择的概率一样大的算法. 首先假设这个数组只有二个元素,设数组a为{1, 2},显然这个数组只有二种可能的排列,要么是{1,2}要么是{2,1}.很容易想到一种方法--只要第二个元素有50%的概率与第一个元素交换即可.用代码表现下: if (rand(

《STL系列》之map原理及实现

上一篇文章<STL系列>之vector原理及实现,介绍了vector的原理及实现,这篇文章介绍map的原理及实现.STL实现源码下载.STL中map的实现是基于RBTree的,我在实现的时候没有采用RBTree,觉得这东西有点复杂,我的map采用的是排序数组(CSortVector).map中的Key存在排序数据中,通过二分查找判断某个Key是否在map中,时间复杂度为O(logN).在用一个CVector存Key和Value,为了方便拿到Key和Value,这里有点冗余,Key被存了两次.现

(Mirage系列之七)Mirage经典案例之管理和发布应用层

在(Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析中我们介绍过,Mirage从逻辑上把终端桌面分层了三层:系统层(包括驱动和基础层),应用层,以及用户数据层.在(Mirage系列之五)Mirage经典案例之桌面驱动和基础层管理中我们讲到Mirage可以灵活方便的管理终端的驱动并且发布基础层.本文将介绍Mirage如何管理终端的应用层. 一个公司往往有很多部门,各部门所需要的工作软件也不尽相同.Mirage通过分层这个核心技术,将应用层剥离出来,使得管

Asp组件初级入门与精通系列之七

在运行前几章的例子,可能或多或少的都会碰上一些问题 如:组件编译后,又要修改,发生"权限被拒绝,'f:\csdn\fcom.dll'"等等的错误. 当asp页面浏览时,打开任务管理器,会看到一个dllhost.exe,用户名为IWAM_YANG的进程.IWAM_YANG会根据计算机名而有所不同. 可以使用以下几种方式来解决 1. 重新启动iis. 在控制面板中找到管理工具->internet信息服务->右键点击左边树图第二层本地计算机->所有任务->重新启动II