? ? 今天部門面試一個(gè)人,面試官給來面試的人除了一道題:大整數(shù)乘法;面試結(jié)果弄得我們術(shù)面試官有點(diǎn)懷疑人生了,順手就抓到我,來你看看這道題,一個(gè)小時(shí)之內(nèi)給我做出來。。。
? ? 一開始,其實(shí)我是,是拒絕的。。。算了,不廢話了,看題:
兩個(gè)若干位(超過10位)的整數(shù)相乘,請(qǐng)寫出正確的結(jié)果,例如
99999999999*99999999999 = 9***************1(我懶的去數(shù)了)
要求:
1.利用OO思想完成代碼
2.支持20位以內(nèi)的大數(shù)乘法
3.盡可能提高效率
加分項(xiàng)
1.代碼調(diào)理結(jié)構(gòu)清晰
2.支持任意位數(shù)相乘
3支持加減乘除
提示:
1.做乘法=做加法
2.累加器原理
3.乘法分配律
4.字符串做存儲(chǔ)
? ? ?簡(jiǎn)單說一句,讓你手工計(jì)算你估計(jì)花點(diǎn)兒時(shí)間也能計(jì)算出來,計(jì)算機(jī)能干嘛?模擬手工計(jì)算嘛!想到這里思路就清晰一半了!分析下我們手工計(jì)算的時(shí)候最關(guān)鍵的是什么:列個(gè)豎式計(jì)算,你可以知道,最關(guān)鍵是進(jìn)位,而且豎式計(jì)算方法中我們會(huì)在計(jì)算不同位數(shù)時(shí)放置在不同的地方,給個(gè)圖
? ? 我們計(jì)算的順序是3*3-》2*3-》6*3,然后該進(jìn)位的地方進(jìn)位;2*3,由于2在十位,計(jì)算結(jié)果為20*3=60,計(jì)算機(jī)模擬需要補(bǔ)1位,6在百位,計(jì)算是600*3=1800,需要補(bǔ)兩位,并進(jìn)一位;這些通過我們代碼模擬就是兩個(gè)東西,補(bǔ)位和進(jìn)位;于是,在代碼中,我們可以分別計(jì)算兩個(gè)數(shù)字字符串每個(gè)位置上面的結(jié)果,并記錄補(bǔ)位和進(jìn)位的情況,最后累加就可以得到一個(gè)完整的字符串了;
? ? 下面具體分析,有什么已有的數(shù)據(jù)結(jié)構(gòu)能很好的表示位數(shù)的情況?對(duì)就是數(shù)組,比如計(jì)算的結(jié)果是1800,我們用一個(gè)長(zhǎng)度為4的int數(shù)組就可以存儲(chǔ)intarr[4]{1,8,0,0}
? ? 接下來是進(jìn)位,就拿最上面的例子來說,兩個(gè)字符串最后一位,9*9,需要進(jìn)一位,于是我們的存儲(chǔ)結(jié)構(gòu)是intArr[2]{8,1},再取第一個(gè)字符串倒數(shù)第二個(gè)數(shù)字和第二個(gè)字符串最后一個(gè)數(shù)字,也就是90*9,進(jìn)一位,在累加到原數(shù)組上面就是int[3]{8,9,1},,這樣一次將兩個(gè)字符串所有位數(shù)上的數(shù)字都乘一遍,得到以下結(jié)果int[15]{1,12,1,12,12,5,6,14,68,12,12,3,45,1,1}(這個(gè)結(jié)果只是列子,不是真實(shí)計(jì)算結(jié)果),我們看到,不同位數(shù)上面有可能大于了10,這是因?yàn)樵谟?jì)算的過程中,只是記錄累加了每個(gè)位置的數(shù)字,并沒有在計(jì)算的時(shí)候進(jìn)行進(jìn)位操作,最后只要遍歷下數(shù)組,進(jìn)下位就行了,比如45,就像百位是45,就進(jìn)個(gè)4到千位,留個(gè)5在百位;那么需要多長(zhǎng)的數(shù)組去計(jì)算兩個(gè)字符串呢??jī)蓚€(gè)字符串長(zhǎng)度總和就是了啦!
分析到此,上代碼(自己隨意寫的,沒有按照啥OO思想啊啥的寫)
public static string caculate(string number1Str,string number2Str)
{
//跳過數(shù)字檢測(cè)
int num1Length = number1Str.Length;
int num2Length = number2Str.Length;
var arrCaculate = new int[num2Length + num1Length ];
for (int i = 0; i < num1Length; i++)
{
for (int j = 0; j < num2Length; j++)
{
int num1 = GetStringNum(i, number1Str);
int num2 = GetStringNum(j,number2Str);
int sum1 = num1 * num2;
int zeroCount = i + j;//補(bǔ)位的數(shù)量
int jinNum = sum1 / 10;//進(jìn)位的數(shù)字
int yuNum = sum1 % 10;//余數(shù)
arrCaculate[zeroCount] += yuNum;//存到相應(yīng)的位置中去
arrCaculate[zeroCount + 1]+= jinNum;
}
}
return CaculateArr(arrCaculate);
}
private static string? CaculateArr(int[] arr)
{
for (int i = 0; i
{
int num = arr[i];//統(tǒng)一計(jì)算進(jìn)位的問題
arr[i] = num % 10;
arr[i + 1] += num / 10;
}
string result = string.Empty;
for (int i = arr.Length-1; i >=0; i--)//依次輸出字符串
{
result += arr[i].ToString();
}
return result;
}
///
/// 倒序
///
///
private static int GetStringNum(int i,string num)
{
string lastCa = num.Substring(num.Length-i-1,1);//獲取正在計(jì)算的一位,倒數(shù)開始,i=0,獲取最后一位數(shù)字
return Convert.ToInt32(lastCa);
}
}
代碼并不多,來看看效果吧
文章寫得少,估計(jì)有些地方?jīng)]說清楚。。。。客官見諒