好久没上帖了,现在把昨天一个晚上和今天一上午的努力写出来,大家互相交流下。
题目的描述我就直接COPY了:
Time Limit: 500MS | Memory Limit: 10000K | |
Total Submissions: 121122 | Accepted: 29574 |
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.899025343415715973535967221869852721 .00000005148554641076956121994511276767154838481760200726351203835429763013462401 43992025569.928573701266488041146654993318703707511666295476720493953024 29448126.764121021618164430206909037173276672 90429072743629540498.107596019456651774561044010001 1.126825030131969720661201
觉得这道题目最难的地方就在于,没有哪个数据类型可以容得下最后那几十位的运算结果。这时候,你可能会脱口而出“用数组不就ok 了”。恩,这是一种很好的想法,可是当你用数组来容纳最后的结果时,有没有感觉那个结果是从何而来的了。一个95.123^12 该怎么去算,才能得到结果了。
下面将我的想法说一下:
运算的过程我是在数组中进行,那么如何在数组中进行计算了。大家小时候还没计算器的时候都是用笔算两数相乘的,即如果 35 * 35 是怎样的一个运算过程了?
即一位的确定 = 两数相乘的低位 + 低位来的进位
那么我们在做两个一位数相乘需要做的工作有:一、相乘+低位
二、向高位进位,如果没有则进位为0
三、最后确定一位的结果为对十求余后的数
那么我们就可以看看最后的代码:
for(i = 0; i < n; i++) { for(f = 0, j = 0; j <= d || f > 0; j++ ) { x = a[j] * b + f; f = x / 10; a[j] = x % 10; } while(a[j] == 0) j--; // 去除前导 的 0 d = j; // d 表示数组中已经被重置的个数 }
须的注明的是,在数组中进行运算的都是单位整型数据,即当输入的数为浮点型时,要先将其一个一个将数字提取出来置入待运算的数组。
#include <iostream> #include <string> /*定义输入的最大数范围是10个*/ #define MAX 10 using std::cin; using std::cout; using std::endl; /* 拿到小数的位数,例如1.234 那么该函数返回的是3*/ int GetNumForDigit(char *str) { int i; int flag = 0; char *original = str; int digit; for(i=0; i < MAX; i++) { if(*str != '?') str++; else{ flag = i; break; } } /*因为在字符串中是以'\0'来结尾的,所以最后求得的位数比原始位大一位*/ flag--; str = original; for(i=0; i < MAX; i++) { if(*str != '.') str++; else{ digit = i; break; } } digit ++; //begin /* 这里进行的运算是处理后置无效零的情况,例如1.0100 , 2.4500000*/ int num = 0; str = original; while(*str != '?') { num++; str++; } num--; str = original; int count = 0; str += num; str--; for(int i=0; i<MAX; i++) { if(*str == '0') { count++; }else{ break; } str--; }//end return flag-digit-count; } /*字符转换数,例如1.23 则转换成123, 特殊的当是1.0100 时 则转换成101,去除后面的无效零*/ int CharTransformInt(char *str) { char *original = str; int num = 0; int result = 0; char temp = NULL; while(*str != '?') { num++; str++; } num -= 2; /*begin 去除后置无效零*/ str = original; bool flag = false; for(int i=0; i < MAX; i++) { if(*str == '.') { flag = true; break; } str++; } str = original; if(flag) { str += num; for(int i=0; i<MAX; i++) { if(*str == '0') { num--; } else { break; } str--; } }//end int num_size = 1; while(--num != 0) { num_size *= 10; } str = original; for(int i = 0; i<MAX; i++) { if(*str != '.' && *str != '?') { temp = *str; /*atoi函数需要注意它的参数是以何种方式结束的*/ result += atoi(&temp) * num_size; num_size /= 10; } str++; } return result; } int main() { int digit = 0, digits = 0, i; char str[MAX]; int n; int a[1000]; for(i=0; i < MAX; i++) { str[i] = '?'; } for(i = 0; i < 1000; i++) //将数组全部置 0 { a[i] = 0; } while(cin>>str>>n) { digit = GetNumForDigit(str); /* 得到小数的位数 */ for(i = 0; i < n; i++) // digits 是得到相乘之后所有的小数位数 { digits += digit; } int b = CharTransformInt(str); int d = 0; a[0] = 1; int j,k,x,f; /*将数置于数组中进行运算,算法思想就是笔算的两数相乘的过程*/ for(i = 0; i < n; i++) { for(f = 0, j = 0; j <= d || f > 0; j++ ) { x = a[j] * b + f; f = x / 10; a[j] = x % 10; } while(a[j] == 0) j--; // 去除前导 的 0 d = j; // d 表示数组中已经被重置的个数 } /*这里处理的情况是当 m < 1 的情况*/ if(d < (digits-1)){ cout << '.'; for(k = 0; k < (digits-1)-d; k++) cout << 0; } /*这里处理的情况是当 m > 1 的情况*/ for(i = d; i >= 0; i--) { if(i == (digits-1)) cout << '.' ; cout << a[i]; } cout << endl; //begin 重置数据 为下一轮循环做准备 for(i=0; i < MAX; i++) { str[i] = '?'; } for(i = 0; i < 1000; i++) //将数组全部置 0 { a[i] = 0; } digit = 0; digits = 0;//end } return 0; }
转载或使用请注明出处http://blog.csdn.net/china_zoujinyong