1001. Exponentiation高精度运算总结
解题思路
这道题属于高精度乘法运算,要求输入一个实数R一个指数N,求实数R的N次方,由于R有5个数位,而N又特别大,因此用C++自带的数据类型放不下.
解题思路是通过数组储存每次乘积结果和底数的每一位数,按照乘法上下算式的方法,计算底数乘数数组每一位与临时结果数组的每一位的乘积,(因为算术运算中是从数的后面往前算的,这里存储数时要先倒序,输出时再颠倒过来,)然后偏移相加,判断得出的临时结果数组的每一位是否大于9,通过除法和取模实现进位和取余.至此得出一个有很多无效数位的结果数组(很多无效的0).
最后判断结果数组的每一位是否为0,先输出小数点前面的数,后输出小数点后面的数,最终得出乘法结果.
这个题目实际上考的是高精度乘法,高精度的其他运算和这个差不多,原理都是一样的.
Description
Problems involving the computation of exact values of very large magnitude and precision are common. For example, the computation of the national debt is a taxing experience for many computer systems.
This problem requires that you write a program to compute the exact value of Rn where R is a real number ( 0.0 < R < 99.999 ) and n is an integer such that 0 < n <= 25.
Input
The input will consist of a set of pairs of values for R and n. The R value will occupy columns 1 through 6, and the n value will be in columns 8 and 9.
Output
The output will consist of one line for each line of input giving the exact value of R^n. Leading zeros should be suppressed in the output. Insignificant trailing zeros must not be printed. Don't print the decimal point if the result is an integer.
Sample Input
95.123 12
0.4321 20
5.1234 15
6.7592 9
98.999 10
1.0100 12
Sample Output
548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201
Hint
If you don't know how to determine wheather encounted the end of input:
s is a string and n is an integer
SourceCode
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string r; //底数
int n,dianwei; //指数,小数点位置
const int len=200; //数位长度
short result[len],jieguo[len],chengshu[6]; //最终结果,临时结果,底数乘数
while(cin>>r>>n)
{
//初始化
for(int i=0;i<len;++i) jieguo[i]=result[i]=0;
for(int i=0;i<6;++i) chengshu[i]=0;
dianwei=0;
//得到底数小数点位置
size_t pos = r.find('.');
//如果底数中有小数点 获取小数点后面有多少位数
if(pos!=string::npos) dianwei=(5-pos)*n;
//把底数中所有不是小数点的数字挑出来转换为int并赋给最终结果,临时结果,底数乘数 得到的是3个5位前后颠倒的数组 之所以颠倒是因为乘法是从后往前乘的
for(int i=5,j=0;i>=0;--i)
{
if(r[i]!='.')
{
jieguo[j]=result[j]=chengshu[j]=r[i]-'0';
++j;
}
}
//当指数大于1时 进行以下运算 等于1时跳过这段程序直接输出
while(n>=2)
{
--n;
//初始化最终结果数组
for(int i=0;i<len;++i) result[i]=0;
for(int i=0;i<5;++i) //从底数乘数的每一位
{
//底数乘数每位数和临时结果每位数相乘的临时变量
int temp;
for(int j=0;j<len;++j) //乘以临时结果的每一位
{
//如果底数乘数某一位是0 没必要乘下去了 跳出当前循环
if(chengshu[i]==0) break;
temp=chengshu[i]*jieguo[j];
//i+j实现乘法相加时的移位
result[i+j]+=temp;
//++t遍历所有结果数组中大于9的数 用除法和取模实现进位和余数
for(int t=i+j;result[t]>9;++t)
{
result[t+1]+=result[t]/10;
result[t]=result[t]%10;
}
}
}
//把一次乘法后的结果赋给临时结果来进行下次乘方
for(int i=0;i<len;++i) jieguo[i]=result[i];
}
//获取最终结果从后数第一个不为0的数作为第一个数的标志位 之所以从后数 是因为之前颠倒的数要颠倒回来了
int firstindex=-1;
for(int i=len;i>=dianwei;--i)
{
if(result[i]>0)
{
firstindex=i;
break;
}
}
//获取 最终结果从前数第一个不为0的数作为最后一个数的标志位
int lastindex=-1;
for(int i=0;i<dianwei;++i)
{
if(result[i]>0)
{
lastindex=i;
break;
}
}
//如果最终结果数组中不全是0 倒序输出结果数组中小数点前面的数
if(firstindex!=-1)
{
while(firstindex>=dianwei)
{
cout<<result[firstindex];
--firstindex;
}
}
//如果最终结果数组中不全是0 倒序输出结果数组中小数点后面的数
if(lastindex!=-1)
{
cout<<'.';
--dianwei;
while(dianwei>=lastindex)
{
cout<<result[dianwei];
--dianwei;
}
}
cout<<endl;
}
}
附录:
一.高精度数的存储
1.字符串输入
#include <iostream>
#include <cstring>
using namespace std;
const int N=100;//最多100位
int main()
{
int a[N+1],i;
string s1;
cin>>s1;//数s1
memset(a,0,sizeof(a)); //数组清0
a[0]=s1.length(); //位数
for(i=1;i<=a[0];i++)
{
a[i]=s1[a[0]-i]-'0';//将字符转为数字并倒序存储.
}
return 0;
}
2.直接读入
#include <iostream>
using namespace std;
const int N=100;//最多100位
int main()
{
int a[N+1],i,s,key;
cin>>key;//数key
memset(a,0,sizeof(a)); //数组清0
i=0;//第0位
while(key) //当key大于0
{
a[++i]=key%10;//取第i位的数
key=key/10;
}
a[0]=i; //共i位数
return 0;
}
3.直接初始化(用a[]存储)
- 初始化为0: memset(a,0,sizeof(a));
- 初始化为1: memset(a,0,sizeof(a));a[0]=1;a[1]=1;
以下程序都只写函数,不写完整程序,所有高精度数存储都满足上述约定。
二.高精度数比较
int compare(int a[],int b[]) //比较a和b的大小关系,若a>b则为1,a<b则为-1,a=b则为0
{
int i;
if (a[0]>b[0]) return 1;//a的位数大于b则a比b大
if (a[0]<b[0]) return -1;//a的位数小于b则a比b小
for(i=a[0];i>0;i--) //从高位到低位比较
{
if (a[i]>b[i]) return 1;
if (a[i]<b[i]) return -1;
}
return 0;//各位都相等则两数相等。
}
三、高精度加法
int plus(int a[],int b[]) //计算a=a+b
{int i,k;
k=a[0]>b[0]?a[0]:b[0]; //k是a和b中位数最大的一个的位数
for(i=1;i<=k;i++)
{
a[i+1]+=(a[i]+b[i])/10; //若有进位,则先进位
a[i]=(a[i]+b[i])%10; //计算当前位数字,注意:这条语句与上一条不能交换。
}
if(a[k+1]>0)
{
a[0]=k+1; //修正新的a的位数(a+b最多只能的一个进位)
}
else
{
a[0]=k;
}
return 0;
}
四、高精度减法
int gminus(int a[],int b[]);//计算a=a-b,返加符号位0:正数 1:负数
{
int flag,i
flag=compare(a,b); //调用比较函数判断大小
if (falg==0)//相等
{
memset(a,0,sizeof(a));return 0; //若a=b,则a=0,也可在return前加一句a[0]=1,表示是 1位数0
}
if(flag==1) //大于
{
for(i=1;i<=a[0];i++)
{
if(a[i]<b[i]){ a[i+1]--;a[i]+=10;} //若不够减则向上借一位
a[i]=a[i]-b[i];
}
while(a[a[0]]==0) a[0]--; //修正a的位数
return 0;
}
if (flag==-1)//小于 则用a=b-a,返回-1
{
for(i=1;i<=b[0];i++)
{
if(b[i]<a[i]){ b[i+1]--;b[i]+=10; //若不够减则向上借一位
}
a[i]=b[i]-a[i];}
a[0]=b[0];
while(a[a[0]]==0) a[0]--; //修正a的位数
return -1;
}
}
五、高精度乘法(高精度乘单精度数,单精度数是指通常的整型数)
int multi1(int a[],long key) //a=a*key,key是单精度数
{
int i,k;
if (key==0){memset(a,0,sizeof(a));a[0]=1;return 0;} //单独处理key=0
for(i=1;i<=a[0];i++)
{
a[i]=a[i]*key;//先每位乘起来
}
for(i=1;i<=a[0];i++)
{
a[i+1]+=a[i]/10;a[i]%=10; //进位
}
//注意上一语句退出时i=a[0]+1
while(a[i]>0)
{
a[i+1]=a[i]/10;a[i]=a[i]%10;i++;a[0]++]; //继续处理超过原a[0]位数的进位,修正a的位数
}
return 0;
}
1001. Exponentiation高精度运算总结的更多相关文章
- POJ 1001 Exponentiation(大数运算)
POJ 1001 Exponentiation 时限:500 ms 内存限制:10000 K 提交材料共计: 179923 接受: 43369 描述:求得数R( 0.0 < R < ...
- 百炼1001: Exponentiation 解题
链接:http://bailian.openjudge.cn/practice/1001/ 思路 乍一看是很简单的题目,但是答案必须高精度输出,因此需要手动实现一个高精度运算方法.如果直接使用int, ...
- 高精度运算专题3-乘法运算(The multiplication operation)
这个专题呢,我就来讲讲高精度的乘法,下面是三个计算乘法的函数,第一个函数是char类型的,要对字符串进行数字转换,而第二个是两个int类型的数组,不用转换成数字,第三个则更为优化,用a数组-b数组放回 ...
- [code]高精度运算
数组存储整数,模拟手算进行四则运算 阶乘精确值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #includ ...
- 系统的讲解 - PHP 浮点数高精度运算
目录 概述 浮点数运算的"锅" 任意精度数学函数 常用数值处理方案 扩展 小结 概述 记录下,工作中遇到的坑 ... 关于 PHP 浮点数运算,特别是金融行业.电子商务订单管理.数 ...
- #C++初学记录(高精度运算)(加法)
高精度运算 不管是int还是double亦或者long long ,这些定义变量都有数据范围的一定限制,在计算位数超过十几位的数,也就是超过他们自身的数据范围时,不能采用现有类型进行计算,只能自己通过 ...
- ICPC Asia Nanning 2017 F. The Chosen One (高精度运算)
题目链接:The Chosen One 比赛链接:ICPC Asia Nanning 2017 题意 \(t\) 组样例,每组给出一个整数 \(n(2\le n\le 10^{50})\),求不大于 ...
- 算法模板 - C++ 高精度运算
C++算法板子 高精度 高精度推荐用python来写,python有大整数,这里写的是关于C++的高精度运算模板 1.高精 * 低精 #include <iostream> #includ ...
- poj 1001 Exponentiation 第一题 高精度 乘方 难度:1(非java)
Exponentiation Time Limit: 500MS Memory Limit: 10000K Total Submissions: 138526 Accepted: 33859 ...
随机推荐
- 脚本之家 前端jQuery js 学习 网站
http://www.jb51.net/books/ http:// www.3wschool.com/
- Jquery基本用法
今天下午讲了Jquery的基本用法:在用Jquery方法时,首先要引用Jquery文件: <script src="jquery-1.11.2.min.js">< ...
- Java日志工具之SLF4J
SLF4J全称为Simple Logging Facade for Java (简单日志门面),作为各种日志框架的简单门面或者抽象,包括 java.util.logging, log4j, logba ...
- 经典网络还是VPC,开发者作何选择?
近两天,关于公有云经典网络(基础网络)与私有网络(VPC)的讨论引发技术圈极大关注,事件起因于有开发者将数据库限制在内网访问,但由于安全组设置的原因,阿里云邻居用户被黑后,牵连到了自己的业务.为此,开 ...
- 浅谈HTML5中的浮动问题
浮动是我们在前端页面中经常会用到的一种布局方式.那什么是浮动呢? 首先我们先来看一下它的定义.浮动是指让元素脱离文档标准流(脱标),按照指定的方向去横向排列.浮动的取值有两个,分别是float:lef ...
- 1197: [HNOI2006]花仙子的魔法
1197: [HNOI2006]花仙子的魔法 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 762 Solved: 443[Submit][Stat ...
- 九度OJ题目1137:浮点数加法 (JAVA)使用BigDecimal四个案例都通过了,但是超时了。
题目描述: 求2个浮点数相加的和 题目中输入输出中出现浮点数都有如下的形式: P1P2...Pi.Q1Q2...Qj 对于整数部分,P1P2...Pi是一个非负整数 对于小数部分,Qj不等于0 输入: ...
- i++和++i 的学习
在<<C++ Primer>> 第四版 5.5中讲解到: ++i:返回操作之后的结果,且是个左值. i++:返回操作之前的结果,且是有右值. // 2_3.cpp : 定义控制 ...
- mysql 索引篇
一.索引优化 索引优化主要还是依赖explain命令,关于explain命令相信大家并不陌生,具体用法和字段含义可以参考官网explain-output,这里需要强调rows是核心指标,绝大部分r ...
- 通过hue提交oozie定时任务
Oozie是什么? Oozie是一种Java Web应用程序,它运行在Java servlet容器——即Tomcat——中,并使用数据库来存储以下内容: 工作流定义 当前运行的工作流实例,包括实例的状 ...