您的位置:首页 > 其它

美团的笔试题中的一种大数除法的方法

2015-09-12 21:42 316 查看
大数是算法语言中的数据类型无法表示的数,其位数超过最大数据类型所能表示的范围,所以,在处理大数问题时首先要考虑的是怎样存储大数,然后是在这种存储方式下其处理的实现方法。

一般情况下大数的存储是采用字符数组来存储,即将大数当作一个字符串来存储,而对其处理是按其处理规则在数组中模拟实现。

大数除法,应该算是四则运算里面最难的一种了。不同于一般的模拟,除法操作步数模仿手工除法,而是利用减法操作实现的。

其基本思想是反复做除法,看从被除数里面最多能减去多少个除数,商就是多少。

我做的思路是先将待除的数后面补零到长度跟被除数一样

循环计算可以被减几次后值为负数,如果为负后,将除数的值去掉一个零,然后将之前不是负数的余数做重复计算,

最后将每次计算的值做大数加和计算,同时最后一次得的余数即为最终的余数

具体的代码如下:

import java.util.ArrayList;

public class Solution {

	public static void main(String[] args) {
		Solution solution=new Solution();
		//System.out.println("423".compareTo("345"));
		String aString="123456789012345678901234567890";
		String bString="345";
		
//		String temp="fjdk  fdjk  fjdk  ";
//		String[] arrStrings=temp.split("\\s{1,}");
		int zeronum=0;
		String tempbString=bString;
		if(tempbString.length()<aString.length())
		{
			for(int i=0;i<1000;i++)
			{
				if(tempbString.length()<aString.length())
				{
					zeronum++;
					tempbString+="0";
				}
				else {
					break;
				}
				
			}
		}
		ArrayList<String> arrayList=new ArrayList<String>(); 
		String  resultString=aString;
		while(zeronum>=0)
		{			
			int nums=0;
			String nodivString=resultString;
			resultString=bigNumberSub(resultString,tempbString);			
			if(resultString.indexOf("-")==-1)
			{
			nums++;
			nodivString=resultString;
			}
			while(resultString.indexOf("-")==-1)
			{
				resultString=bigNumberSub(resultString,tempbString);
				if(resultString.indexOf("-")==-1)
				{
				nums++;
				nodivString=resultString;
				}
			}
			String result1=nums+"";
			for(int i=0;i<zeronum;i++)
			{
				result1+="0";
			}
			arrayList.add(result1);
			zeronum--;
			tempbString=tempbString.substring(0,tempbString.length()-1);
			resultString=nodivString;
		}
		
		//此时结束后的resultString是余数
		String buisString="0";
		for(int i=0;i<arrayList.size();i++)
		{
			buisString=bigNumberAdd(buisString, arrayList.get(i));
		}
		System.out.println(buisString+" "+resultString);
	}

	 public static String bigNumberAdd(String f, String s) {
	        //翻转两个字符串,并转换成数组
	        char[] a = new StringBuffer(f).reverse().toString().toCharArray();
	        char[] b = new StringBuffer(s).reverse().toString().toCharArray();
	        int lenA = a.length;
	        int lenB = b.length;
	        //计算两个长字符串中的较长字符串的长度
	        int len = lenA > lenB ? lenA : lenB;
	        int[] result = new int[len + 1];
	        for (int i = 0; i < len + 1; i++) {
	            //如果当前的i超过了其中的一个,就用0代替,和另一个字符数组中的数字相加
	            int aint = i < lenA ? (a[i] - '0') : 0;
	            int bint = i < lenB ? (b[i] - '0') : 0;
	            result[i] = aint + bint;
	        }
	        //处理结果集合,如果大于10的就向前一位进位,本身进行除10取余
	        for (int i = 0; i < result.length; i++) {
	            if (result[i] > 10) {
	                result[i + 1] += result[i] / 10;
	                result[i] %= 10;
	            }
	        }
	        StringBuffer sb = new StringBuffer();
	        //该字段用于标识是否有前置0,如果有就不要存储
	        boolean flag = true;
	        for (int i = len; i >= 0; i--) {
	            if (result[i] == 0 && flag) {
	                continue;
	            } else {
	                flag = false;
	            }
	            sb.append(result[i]);
	        }
	        return sb.toString();
	    }
	 public static String bigNumberSub(String f, String s) {
	       // System.out.print("减法:" + f + "-" + s + "=");
	        // 将字符串翻转并转换成字符数组
	        char[] a = new StringBuffer(f).reverse().toString().toCharArray();
	        char[] b = new StringBuffer(s).reverse().toString().toCharArray();
	        int lenA = a.length;
	        int lenB = b.length;
	        // 找到最大长度
	        int len = lenA > lenB ? lenA : lenB;
	        int[] result = new int[len];
	        // 表示结果的正负
	        char sign = '+';
	        // 判断最终结果的正负
	        if (lenA < lenB) {
	            sign = '-';
	        } else if (lenA == lenB) {
	            int i = lenA - 1;
	            while (i > 0 && a[i] == b[i]) {
	                i--;
	            }
	            if (a[i] < b[i]) {
	                sign = '-';
	            }
	        }
	        // 计算结果集,如果最终结果为正,那么就a-b否则的话就b-a
	        for (int i = 0; i < len; i++) {
	            int aint = i < lenA ? (a[i] - '0') : 0;
	            int bint = i < lenB ? (b[i] - '0') : 0;
	            if (sign == '+') {
	                result[i] = aint - bint;
	            } else {
	                result[i] = bint - aint;
	            }
	        }
	        // 如果结果集合中的某一位小于零,那么就向前一位借一,然后将本位加上10。其实就相当于借位做减法
	        for (int i = 0; i < result.length - 1; i++) {
	            if (result[i] < 0) {
	                result[i + 1] -= 1;
	                result[i] += 10;
	            }
	        }

	        StringBuffer sb = new StringBuffer();
	        // 如果最终结果为负值,就将负号放在最前面,正号则不需要
	        if (sign == '-') {
	            sb.append('-');
	        }
	        // 判断是否有前置0
	        boolean flag = true;
	        for (int i = len - 1; i >= 0; i--) {
	            if (result[i] == 0 && flag) {
	                continue;
	            } else {
	                flag = false;
	            }
	            sb.append(result[i]);
	        }
	        // 如果最终结果集合中没有值,就说明是两值相等,最终返回0
	        if (sb.toString().equals("")) {
	            sb.append("0");
	        }
	        // 返回值
	       // System.out.println(sb.toString());
	        return sb.toString();
	    }

}


计算结果:357845765253175880873143675 15

商为:357845765253175880873143675

余数为:15
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: