Time Limit: | Memory Limit: | |
Total Submissions: | Accepted: |
Description
Input
Output
Sample Input
95.123 12 0.4321 20 5.1234 15 6.7592 9 98.999 10 1.0100 12
Sample Output
548815620517731830194541.899025343415715973535967 221869852721 .000000051485546410769561 219945112767671548384817 602007263512038354297630 13462401 43992025569.928573701266488041146654 993318703707511666295476 720493953024 29448126.764121021618164430206909 037173276672 90429072743629540498.107596019456651774561044 010001 1.126825030131969720661201
分析:
这题是乘幂计算,所以关键是输入和储存,还有乘法算法的实现.
1、数据的输入与存储;
(1)数组:每个数组元素存储1位(在优化时,这里是一个重点!),有多少位就需要多少个数组元素;
优点:每一位都是数的形式,可以直接加减;运算时非常方便
优点:能直接输入输出,输入时,每两位数之间不必分隔符,符合数值的输入习惯;
缺点:字符串中的每一位是一个字符,不能直接进行运算,必须先将它转化为数值再进行运算;运算时非常不方便(注意‘0’的问题)。
2、乘法算法的实现
思路:按照竖式乘法计算的方式,就像我们以前打草稿那样.简单点来说就是:申请一个空间为250的一维数组m[250]。然后里面只存放每次相乘得到的结果。乘数用m_data表示.把m[]中的每位数每次都乘以m_data.再与原有的m[]相加,要注意进位的处理.具体的看代码吧
3、完整代码:
注释的比较清楚,但是这个算法效率很差.还没有优化.反正思路就是这样.
#include <iostream>
#include <stdio.h>
using namespace std;
//功能:计算,并将结果储存在数组m中
//参数:d:要计算的大数;n1:指数幂;m[]用于存放结果
//思路:按照竖式乘法计算的方式,来获得.每一次的结果都存在数组m[]中
void calculate(int d, int n1, int m[])
{
int m_data = d;
int n = n1;
int data = m_data;
int j = 250;
//将大数先存到m中
while(data/10 != 0 || data%10 != 0 )
{
j--;
m[j] = data%10;
data = data/10;
}
int i = j-1;//设置i从m数组中已经存在数的前一位开始
//指数幂,循环n次
while(--n)
{
//将m中所有的数都循环一次
for (j = i+1; j < 250; j++)
{
int temp = m[j] * m_data; //将数组m中,每一位数都与大数相乘
m[j] = 0;
int t = j;
//将相乘的结果与原先在m中的相加
while(temp / 10 != 0 || temp % 10 != 0)
{
m[t] = m[t] + temp % 10;
int t1 = t;
//若大于9则要进位
while(m[t1] > 9)
{
int tem2 = m[t1];
m[t1] = tem2 % 10;
t1--;
m[t1] = m[t1] + (tem2 / 10);
}
t--;
temp = temp / 10;
}
}
i=0;
while(m[i]==0)i++; //找到m中第一个非零的位置
i--;
}
}
//功能:确定r[]是否有小数点
//其实这个函数不必要.等优化的时候再改
int wheredot(char r[])
{
for (int i = 0; i < 6; i++)
{
if (r[i] != '.')
{
continue;
}else {
return i;
}
}
return 5;
}
//功能:输出计算好的m[],并根据小数位数,添加小数点.
void output(int m[], int decimals, int n)
{
//得到m中第一个不为0的数
int f = 0;
while (m[f] == 0) f++;
//得到总的小数位数
int sumDecimals = n * (decimals);
//当第一个不为0的数在小数点之前,则先输入数,当到小数点时,输出小数点
if (f <= (250-sumDecimals))
{
for (int i = f; i < 250; i++)
{
//当i的位置等于(250 -小数的位数,就是已经输出的位数)时,输出小数点
if (250 - sumDecimals == i )
{
cout << '.';
}
cout << m[i];
}
} else {
//当第一个不为0的数在小数点之后,先输出小数点.后面的0也不省略
for (int i = (250 - sumDecimals); i < 250; i++)
{
if (250 - sumDecimals == i )
{
cout << '.';
}
cout << m[i];
}
}
}
//功能:从输入的r[]获得大数,并确定小数点位数
//思路:将r去掉小数点和小数末尾的0后,在转化成大数.
int large(char r[], int *decimals)
{
int m_data = 0;
int number[6] = {-1,-1,-1,-1,-1,-1};//将r数组中去掉小数点和最后的0,再存入.
int m_dot = 0; //小数点位于哪里
int m_decimals = 0; //小数位数
m_dot = wheredot(r);
m_decimals = 5 - m_dot;
if (m_decimals != 0)
{
//有小数
int l = 5;
while(r[l] == '0')
{
l--;//去掉r中小数后的0
m_decimals--;//小数位数-1
}
for (int i = l, j = 5; i >= 0; i--)
{
if (r[i] != '.')
{
//将数组r中的字符数转为int型后存入数组number[]中
number[j] = r[i] - '0';
j--;
} else {
//跳过数组
continue;
}
}
} else {
//没有小数
for (int i = 5, j = 5; i >= 0; i--)
{
number[j] = r[i]- '0';
j--;
}
}
for (int i = 0; i < 6; i++)
{
if (number[i] != -1)
{
m_data = number[i] + m_data * 10;
}
}
*decimals = m_decimals;
return m_data;
}
int main()
{
char r[6] = {'0'}; //底数
int n; //指数
//输入
while(cin >> r >> n)
{
int m[250] = {0}; //存放结果
int m_data = 0; //小数点去掉后的大数
int *m_decimals = new int; //小数位数
m_data = large(r, m_decimals); //获得大数
calculate(m_data, n, m); //计算,并将结果储存在数组m中
output(m, *m_decimals, n);//输出结果,添加上小数点.
delete m_decimals;
cout << endl;
}
return 0;
}
4.java实现
如果是用java的话,就很好解决了.直接使用Java中的BigDecimal类就可以了.下面对BigDecimal类,简单介绍一下:
Java在java.math包中提供的API类BigDecimal,用来对超过16位有效位的数进行精确的运算。float和double只能用来做科学计算或者是工程计算,在商业计算中要用java.math.BigDecimal。BigDecimal所创建的是对象,我们不能使用传统的+、-、*、/等算术运算符直接对其对象进行数学运算,而必须调用其相对应的方法。方法中的参数也必须是BigDecimal的对象。
BigDecimal一共有4个构造方法:
代码如下:
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner cin = new Scanner(System.in);//用于输入读取
while (cin.hasNext())
{
BigDecimal data = cin.nextBigDecimal();
int n = cin.nextInt();
BigDecimal result;
result = data.pow(n).stripTrailingZeros();//去掉小数点后面的零
String m_string = result.toPlainString();
if (m_string.charAt(0) == '0') {
m_string = m_string.substring(1);
}
System.out.println(m_string);
}
}
}