作者game0416 (凤狼)
看板NTUE-CS102
标题Re: [闲聊] 程设作业
时间Thu May 13 23:11:03 2010
两个礼拜前的printf大概推这个对岸连结
http://blog.pfan.cn/wentao/10152.html
其他说明就略,有问题再说
然後我不熟悉能怎样用的继承相关也都略
不然写起来就是长课本那样而已(死)
记得继承等级我觉得就差不多啦...啦
所以这篇着重在这次作业的大数(BigInteger)这样。
--
我不懂为什麽要从乘法开始讲大数...
虽然说是大数乘小数,不要特意写成串列不会太难
特意写成串列的话...脑袋要够活,然後我没这个爱对於一千位的大数写串列
等有需要的时候再看看....不然就不要用C或换编译器啦(被殴)
因为提到大数,所以我想先从简单的加法开始慢慢谈
然後这段对於大数的说明,全都建立在"大数对大数"为讨论前提
讲是讲大数,不过拿出来当例子的其实只是 66 跟 125 这样的三位数字简单说明
: 作业以外的部份不详加code....不然写完都不知道几点了(远目)
从数学基本的加法来当作开始
首先,对於大数的概念很单纯,就是去模拟我们手算直式的行为而已
不管加减乘除取余数开根号什麽的都是这样,保持这个观念去解大数会好很多
--
以66+125来说,我们会这样做...
6 6 1.先把个位对个位,数字排好
+ 1 2 5
----------
1 1 2.从个位对个位开始加总
6
1 2
----------
9 1 3.将十位加总、计入从个位进位来的数
1
----------
1 9 1 4.将十位加总、计入从十位进位来的数
用这样的处理顺序来得到66+125=191,将这样的过程转换成阵列/串列排列
用每个阵列/串列上的一个元素表示一位来运作,然後藉由语言让电脑实作
就是大数的概念,剩下大概都只是优化的部份而已
--
减法一样...这次改成125-66
1 2 5 1.一样先把个位对个位,数字排好
- 6 6
----------
-1 9 2.从个位对个位开始相减
+ 1 2 然後将结果与被减数相加
----------
1 1 9
- 6 3.将十位相减
---------- 然後将结果与被减数相加
-1 5
+ 1 0 9
----------
5 9
像这样逐步去做完减法,即大数减法...判断正负号就看第一位就好
--
乘法亦同...只是大数对大数需要三条阵列来做处理会比较好
这次求125*66
1 2 5 1.一样先把个位对个位,数字排好
* 6 6
----------
7 5 0 2.乘数每位先分别对被乘数每位相积
7 5 0
----------
8 2 5 0 3.将其各位数排好相加
如此得 125*66=8250
这里要注意是...第二步最好另外设一条阵列与被乘数、程数分别出来
避免盖掉其他位数,让结果数值有问题
前面加减法比较不用管这个这样
针对除法则先略..没写好过(摊)
内容是用"连减"去处理数值,然後纪录减了几次就可以了QQ
: 乘法也能用连加啦...建构式数学有它的好
--
上面大概说明了一下,再来回到这次的作业..
因为是大数乘小数、1000位以内,在某些地方可以比大数乘大数偷懒
: 遇到int范围边缘的阶层会出问题...不过因为题目不会发生就跳一点无所谓
举例一样是125*66,这里125是大数,66是用int宣告的数值
先想像有个
int bignum[
4]={
0,
1,
2,
5};
: 这部分只是我喜欢这样...彦廷写成{5,2,1,0}对阵列处理会比较方便
: 我只是觉得125比较符合我脑袋模拟的感觉,小作业不要求执行时间(逃跑
这里我们先把刚才直式改写成这样的感觉
1 2 5
* 66 1.同样把个位对个位...
---------- 可是把小数整体视为个位
330
132 2.逐个相乘
+ 66
----------
--
此时,
bignum[
3] (我们用来装个位数的那一个元素) 里面装330
显然与我们一开始打算只装一位不合
所以就让它做进位处理
bignum[
2] = bignum[
2] + bignum[
3]/
10;
: int / int,余数会变小数而被主动删去...至少对g++是这样啦
: 要避免不同编译器有问题的话可能注意一下比较好
然後让
bignum[
3] = bignum[
3]%
10;
用以留下个位数字,这样就算对个位的进位结束
再往上做十位...
现在bignum[
2] ==
165
同样对其进位
bignum[
1] = bignum[
1] + bignum[
2]/10
bignum[
2] = bignum[
2]%
10;
类推
bignum[
0] = bignum[
0] + bignum[
1]/10
bignum[
1] = bignum[
1]%
10;
--
最後,再依项输出
for (
int i=
0;i<
4;i++)
cout <<bignum[i];
就会得到 8250 这样的输出
回到题目本身要求n!
就直接让人输入n,以for回圈来跑1到n的乘数
预设的被乘数个位设为1,配合上面这个思考作法就能直接做出来这个作业了
下页起一样附个没优化的code,乱写一气的就不要在意了
写法上我脑袋直观把个位排最後有浪费执行时间跟行数就是了
执行上有问题一样还是请通知一下Orz
--
#include<iostream>
#define max 1000
using namespace std;
int main()
{
int input;
while (cin >>input){
int arr[max];
for (
int i=
0;i<
1000;i++)
arr[i]=
0;
arr[max-1]=
1;
if (input>
1){
for (
int i=
2;i<=input;i++){
for (
int j=
0;j<max;j++)
arr[j]*=i;
for (
int j=max-
1;j>
0;j--){
arr[j-1]+=arr[j]/
10;
arr[j]%=
10;
}
}
}
int start=
0;
for (
int i=
0;i<max;i++)
if (arr[i]!=
0){
start=i;
break;
}
for (start;start<max;start++)
cout <<arr[start];
cout <<endl;
}
}
--
所恐惧的,不是没有知识的大众 所憎恨的,不是深沉幽暗的人心
而是自以为是的思考之声 而是自恃甚高的执法者
所毁灭的,不是温馨和谐的世界 这是我最後的期许,没有愤怒、没有悔恨
而是自欺欺人的梦境 只剩下,浑沌的死亡呼吸
节自 新月神话-弑王者
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 58.114.65.42
1F:推 gcobc12632:凤狼必推 05/13 23:11
2F:推 Arashinoon:未看先推 05/13 23:15
3F:推 garfield112:先END再推 05/13 23:18
4F:→ j2612280:"不要用C或换编译器啦"...... 05/13 23:31
5F:→ game0416:我错了吗QQ 05/13 23:32
6F:→ j2612280:没啦..只是突然无言而已.. 05/13 23:34
7F:→ game0416:QQ 05/13 23:37
8F:→ game0416:换语言有内建大数,换编译器把阵列开更大嘛... 05/13 23:37
※ 编辑: game0416 来自: 220.130.128.171 (05/14 17:41)