• POJ 1001 解题报告 高精度大整数乘法模版


    题目是POJ1001 Exponentiation  虽然是小数的幂 最终还是转化为大整数的乘法  

    这道题要考虑的边界情况比较多 做这道题的时候,我分析了 网上的两个解题报告,发现都有错误,说明OJ对于错误的判断还不够严厉. 对边界情况的讨论其实应该是思维严密的表现,当然这并不能表明我写的一点错误都没有,只是多多分析一下还是很有好处的。

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <algorithm>
    #define MAXSIZE 7
    using namespace std;
    string result;
    string tmp;
    string base;//基数;
    
    //从此可以看到c比c++的优越之处;
    string mul(string multiplied,string multiplier)
    {
    	tmp = string(150,'0');
    	int carrier=0;//进位;
    	int answer=0;//得数;
    	int j = 0;int i = 0;
    	for (i = 0; i < multiplied.length(); i++)
    	{
    		carrier = 0;
    		for (j = 0; j < multiplier.length(); j++)
    		{
    			answer  = ((multiplier.at(j)-'0')*(multiplied.at(i)-'0') + (tmp.at(i+j)-'0') + carrier )%10;
    			carrier = ((multiplier.at(j)-'0')*(multiplied.at(i)-'0') + (tmp.at(i+j)-'0') + carrier )/10;
    			tmp[i+j] = answer + '0';
    		}
    		if (carrier)
    		{
    			tmp[i+j] = carrier + '0';
    		}
    	}
    	//tmp[i+j]='/0';//不知道这个是否有必要;
    	tmp = tmp.substr(0,i+j);
    	return tmp;
    }
    string expo(string multier,int time)
    {
    	if (time==1)//如果要乘一次,直接返回;
    	{
    		return multier;
    	}
    	result = expo(multier,time-1);
    	/*下面计算multier与result的乘积 */
    	return mul(result,multier);
    
    }
    
    int main()
    {
    
    #ifndef ONLINE_JUDGE
        freopen("D://code//acm//txt//11.txt","r",stdin);//如果不是在OJ上运行那么就从本地的这个文件中读取信息;
    #endif   
    	int time;//次数;
    	
    	while(cin>>base>>time)
    	{
    		/*下面的代码可以用来处理无效0*/
    		int start = 0;
    		int end   = base.length()-1;
    		int pos  = base.find('.');
    		while( start <= base.length()-1 && base.at(start)=='0' )
    		{
    			start++;
    		}
    		if (pos!=-1)//如果存在小数点;
    		{
    			while (end>=0 && base.at(end)=='0')
    			{
    				end--;
    			}
    		}
    		
    		//执行之后start指向第一个不为0的位,end指向小数部分最后一个不为0的整数,如果没有小数则指向个位部分;
    		/*下面取出有效部分*/
    		base = base.substr(start,end-start+1);
    		/*下面记下小数点位置并除去小数点*/
    		pos = base.find('.');
    			/*下面计算结果中小数部分的长度,那么它也可以作为结果倒置的时候的下标*/
    		if(pos!=-1){
    			int len = base.length();
    			base.erase(pos,1);
    			pos = time * (len-pos-1);
    		}
    		/*下面可以将这个字符串倒置*/
    		/*cout<<base<<" ";*/
    		reverse(base.begin(),base.end());
    		/*cout<<base<<endl;*/
    		
    		/*下面开始根据time次数进行大整数乘法*/
    		end = 0;
    		result = expo(base,time);
    		if(pos!=-1){
    			result.insert(pos,1,'.');
    			
    			while (result.at(end) == '0')
    			{
    				end++;
    			}
    			//判断剩下的最后一位是不是小数点;
    			if ( result.at(end) == '.')
    			{
    				end++;
    				
    			}
    		}
    		//下面删去前面多余的0;
    		start = result.length()-1;
    		while (start >=0 && result.at(start) == '0')
    		{
    			start--;
    		}
    		if(start<end)//表示结果是0;
    		{
    			result = "0";
    		}else{
    			result = result.substr(end,start-end+1);
    			reverse(result.begin(),result.end());
    		}
    		////判断剩下的整数是不是0;
    		//end = result.length()-1;
    		//while (end >=0 && result.at(end) == '0')
    		//{
    		//	end--;
    		//}
    		//if (end == -1)
    		//{
    		//	result = "0";
    		//}
    		cout<<result<<endl;
    	}
    
    	return 0;
    }


    写这个代码我所得到的 :

    一、c与c++ java  各有各的优势 不能互相替代(永远不可能,所以不要妄想只学一门语言)

    1.c语言从来不要你急什么东西,库函数也不多,没什么记忆的压力,当你用c语言写东西的时候,你会感觉到好像是你自己在说话,好像这语言你你发明的似得,也许这就是孔子说的七十而从心所欲不逾矩(装逼开始,我第一次感受到编程就像自己在跟电脑说话是在高中一年级的VB课上,不过只学过一学期,但是那是我编程的启蒙,那时候我总是在班上第一个编出程序,但这并不是最变态的,最变态的是,在此之前我从来没见过键盘,电脑倒是远远的见过,装逼时间到)。这种感觉我从没有在c++上获得过,因为我用c++写的代码很多第一遍都会有错误。

    2.c++标准函数太多了学的时间长 而且还有重载所以一个函数不容易记住,并且记住了参数顺序也记不住,所以大概c++语法是用来查的吧。

    3.c++标准函数多的好处是 你写代码效率会比较高,比如reverse函数,不用实现一些东西,另外一些函数虽然在c中有替代品但是实现的并不好,比如find函数在c中是strchr函数但是返回的是个指针,指针就各种不爽了。但是不好的东西就是c++不精确,比如这里记录中间过程结果的是string类型,但是string对象是不允许对内容进行修改的,你进行的操作大概是新建了另一个对象效率自然不行,虽然c++兼容c语法,但说到底还是c。

    4.当然c++写项目还是没有java爽。

    二、有用的c++函数总结

    find()函数; string成员函数有这个,algorithm库中也有这个 ,可以在容器中查找元素
    string的at函数,比如string str;  str.at(pos)能够检查越界 比 str[pos] 安全。当然你可以根据自己的需求选择使用哪一种表示方式,但是在c中你就没的选
    erase函数可以选择性地删除字符串中一部分,我们可以想见其效率有多慢,但是总比自己写代码要爽
    insert函数 就是插入函数  
    reverse函数 反转字符串的一部分  是algorithm库里面的,可以对容器进行操作;

    三、对以后写代码有用的模版

    string mul(string multiplied,string multiplier)
    {
    	tmp = string(150,'0');
    	int carrier=0;//进位;
    	int answer=0;//得数;
    	int j = 0;int i = 0;
    	for (i = 0; i < multiplied.length(); i++)
    	{
    		carrier = 0;
    		for (j = 0; j < multiplier.length(); j++)
    		{
    			answer  = ((multiplier.at(j)-'0')*(multiplied.at(i)-'0') + (tmp.at(i+j)-'0') + carrier )%10;
    			carrier = ((multiplier.at(j)-'0')*(multiplied.at(i)-'0') + (tmp.at(i+j)-'0') + carrier )/10;
    			tmp[i+j] = answer + '0';
    		}
    		if (carrier)
    		{
    			tmp[i+j] = carrier + '0';
    		}
    	}
    	//tmp[i+j]='/0';//不知道这个是否有必要;
    	tmp = tmp.substr(0,i+j);
    	return tmp;
    }

    作用:这个可以用来进行大整数乘法;
    前置条件:字符串里面存的整数和被整数都反转过(即字符串的低位放的是整数的低位,一般你输入一个大整数的话最高位存放在下标为0的地方);
    后置条件:返回一个反转了的积

    四、一些已经掌握的良好习惯

    1.打得一手好注释;
    2.
    #ifndef ONLINE_JUDGE
        freopen("D://code//acm//txt//11.txt","r",stdin);//如果不是在OJ上运行那么就从本地的这个文件中读取信息;
    #endif   
    3、等等

    五、本题所体现的边界条件或者需要注意的讨论点 

    1.这个题的运算结果多余的零,不能要,这个是个复合的条件但是并不等价于把左边的0和右边的0都去掉,因为有一种可能是输入的数据从头到尾都是0,这样将会出错,不过POJ好像没有对这个结果进行测试,我们可以认为这是POJ的疏忽之处.
    2.另外有些人写的代码默认给的数据里一定有小数点,不巧的是POJ系统后台测试的数据确实都是带小数点的,但题目中并没有这个条件,我们可以认为这是POJ的疏忽之处,所以我们应该讨论这种情况,小数部分都是0,这样你如果得到1234.000 难道你要输出1234.吗,显然不可取,不过网上有的代码确实是这样的。


  • 相关阅读:
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    xgqfrms™, xgqfrms® : xgqfrms's offical website of GitHub!
    程序员,你最重要的选择是和谁结婚,你最重要的能力是赚钱,钱和女友两手抓...
    计算机网络基础 — Linux 流量控制
    Oracle 20c 新特性:持久化内存数据库
    数据库每日一题 2020.04.30
  • 原文地址:https://www.cnblogs.com/dragonfive/p/4486210.html
Copyright © 2020-2023  润新知