高精度POJ1001
今天看到这道题了 poj1001 题目地址是http://bailian.openjudge.cn/practice/1001/
英文看得懂,可是算法不明白,所以转别人的文章,留着给学生看看:乔高建(高精度)
解题思路
这道题属于高精度乘法运算,要求输入一个实数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 12Sample Output
548815620517731830194541.899025343415715973535967221869852721
.00000005148554641076956121994511276767154838481760200726351203835429763013462401
43992025569.928573701266488041146654993318703707511666295476720493953024
29448126.764121021618164430206909037173276672
90429072743629540498.107596019456651774561044010001
1.126825030131969720661201Hint
If you don't know how to determine wheather encounted the end of input:
s is a string and n is an integerSourceCode
#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;
}
高精度POJ1001的更多相关文章
- POJ-1001 Exponentiation 高精度算法
题目链接:https://cn.vjudge.net/problem/POJ-1001 以前写过一个高精度乘法,但是没有小数点,实现起来也没什么难得, 现在把代码都般过来,等会把旧电脑弄一弄,暂时就不 ...
- C# 高精度求幂 poj1001
高精度求幂 public static char[] exponentiation(string a,int r) { ]; string b = ""; string c = a ...
- poj1001(高精度)
Exponentiation Time Limit: 500MS Memory ...
- 求高精度幂(poj1001)
Description Problems involving the computation of exact values of very large magnitude and precision ...
- CSharpGL(28)得到高精度可定制字形贴图的极简方法
CSharpGL(28)得到高精度可定制字形贴图的极简方法 回顾 以前我用SharpFont实现了解析TTF文件从而获取字形贴图的功能,并最终实现了用OpenGL渲染文字. 使用SharpFont,美 ...
- 递推+高精度 UVA 10497 Sweet Child Makes Trouble(可爱的孩子惹麻烦)
题目链接 题意: n个物品全部乱序排列(都不在原来的位置)的方案数. 思路: dp[i]表示i个物品都乱序排序的方案数,所以状态转移方程.考虑i-1个物品乱序,放入第i个物品一定要和i-1个的其中一个 ...
- [Template]高精度模板
重新写一下高精度模板(不要问我为什么) 自认为代码风格比较漂亮(雾 如果有更好的写法欢迎赐教 封装结构体big B是压位用的进制,W是每位长度 size表示长度,d[]就是保存的数字,倒着保存,从1开 ...
- Code[VS] 3123 高精度练习之超大整数乘法
FFT 做 高精度乘法 #include <bits/stdc++.h> ); struct complex { double a, b; inline complex( , ) { a ...
- Java 高精度数字
BigInteger // 高精度整数 BigDecimal //高精度小数 小数位数不受限制
随机推荐
- 理解vue 修饰符sync
也是在vux中看到了这个sync 现在我们来看看vue中的sync 我们先看下官方文档:vue .sync 修饰符,里面说vue .sync 修饰符以前存在于vue1.0版本里,但是在在 2.0 中移 ...
- Linux核心命令使用方法
一.Linux命令行常用快捷键 ctrl + c cancel 取消当前的操作 ctrl + l (小写字母L) clear(命令)清空当前屏幕 ctrl + d 退出当前用户 ctrl + r 查找 ...
- JGUI源码:开发中遇到的问题(11)
1.IE8下浏览器下css body边缘要留一个像素,如果不留的话,很有可能看不到最边缘的像素. 2.同一种颜色在深色背景和浅色背景下给人的感觉不一样,在深色背景下,给人感觉特别亮,所以深色背景下的颜 ...
- Eclipse——在eclipse上安装Pydev插件实现python编程
介绍:2003年7月16日,以 Fabio Zadrozny 为首的三人开发小组在全球最大的开放源代码软件开发平台和仓库 SourceForge 上注册了一款新的项目,该项目实现了一个功能强大的 Ec ...
- 使用hql动态创建对象问题
前段时间由于需求要添加报表数据,调整ireport后,打印pdf文件出现数据错位的情况,调试发现不是ireport问题,就查看了后台传送的数据,最后发现传送的对象属性值已经就是错位的,那就是获取对象时 ...
- python3抓图学习-百度贴吧
# coding=utf-8 from bs4 import BeautifulSoup import urllib.request import os import time def downlao ...
- python双端队列-collection模块
双端队列(double-ended queue,或者称deque)在需要按照元素增加的顺序来移除元素时非常有用.其中collection模块,包括deque类型. 使用实例:
- 如何用ps简单快速扣头发丝
好久不用PS抠图,今天接到一个小任务,换背景,以前一直用通道的办法,但用通道比较费劲,发现一个更简单的办法,就是用快速蒙版+调整边缘. 这张是原图: 1.先用快速蒙版制作选取(Q) 再按Q,退出快速蒙 ...
- luogu P3810 三维偏序(陌上花开)cdq分治
题目链接 思路 对一维排序后,使用$cdq$分治,以类似归并排序的方法处理的二维,对于满足$a[i].b \leq a[j].b$的点对,用树状数组维护$a[i].c$的数量.当遇到$a[i].b&g ...
- 423 重温Java Script and jQuery 葵花宝典 Bootstrap
Bootstrap需要引的三个文件 <link rel="stylesheet" href="css/bootstrap.css"> 表格元素 ...
