2016年9月14日 星期三

python 程式設計50題測試範例-40 大數加法 -42 大數乘法

40、大數加法,兩個100位數以內的數字相加,列印出結果。

42、大數乘法,兩個100位數以內的數字相乘,列印出結果。

大數問題
一、基本觀念
在某些情況下,我們必須處理位數相當多的一個整數,例如 100 位數,系統內建的資料型態不管是 intlong intlong long int 等,位數顯然都不夠用。要解決這個問題,我們必須自己用程式來處理,最簡單的方法,就是模仿人工處理數字的方式,也就是把數字拆成一個位數一個位數,這個時候我們可以用一個陣列來完成這個動作。不過,這樣一來,所有對於這種超大整數的處理,包括輸入一個大數、兩個大數相加、印出一個大數等等,都需要我們自己寫一個函數來處理。至於這個陣列要用什麼樣的資料型態,因為兩個一位數相乘也不過才 81,所以我們可以用 char 的陣列來記錄一個超長整數,如:
char n[300];
就可以記錄 300 位數的資料。前面提到大數的輸入及輸出,都需要我們自己寫函數來處理,我們分別把它們定名為 Input()  Print()
#include <stdio.h>
#include <string.h>
#define LEN 300
int Input(char n[])
{
}
void Print(char n[])
{
}
void main()
{
 char a[LEN];
 Input(a);
 Print(a);
}
上面第三行 #define LEN 300 的意思,即是定義一個常數叫做 LEN,而它的值是 300,下面用到 LEN 的地方,在執行的時候便會自動變成 300。這樣寫的好處是,如果我們有好個地方都用到 300 這個數字,但是後來發現不夠用了,要將它改成 1000,這個時候要一行一行改,還可能不小心漏掉,如果用 #define 定義一個常數,則只要改一個地方就行了。接下來我們看到 Input() 函數要做的步驟:
1.  把該陣列的每一格數字歸零。
2.  將使用者輸入的數字以字串方式存到另一個字串。
3.  計算該字串的長度。
4.  從該字串的尾端(即個位數)開始一個一個位數往左,將它轉換成數字後,存到陣列對應的格子中。
我們把上面提到的字串及超長整數的陣列做一個比較:
字串
s[0]
s[1]
s[2]
s[3]
s[4]
s[5]
s[6]
s[7]
s[8]
s[9]
'1'
'2'
'3'
'4'
'5'
'6'
0
×
×
×
陣列
n[0]
n[1]
n[2]
n[3]
n[4]
n[5]
n[6]
n[7]
n[8]
n[9]
6
5
4
3
2
1
0
0
0
0
上面提到的 Input() 的程式碼可以寫成:
int Input(char n[])
{
 char s[LEN];
 int i, l;
 for(i=0; i<LEN; i++)
   n[i]=0;
 if(scanf("%s", s)<1) return -1;
 l=strlen(s);
 for(i=0; i<l; i++)
   n[i]=s[l-i-1]-'0';
 return 0;
}
上面的 Input() 函數為了要得知是否有資料輸入,所以我們利用傳回值 0 代表輸入成功,傳回 -1 代表傳入失敗。至於 Print() 函數要做的步驟為:
1.  從該陣列最後面往回找到第一個不是 0 的數字。
2.  從該位數字往左邊依序把它們一個一個印出來。
3.  印出換行符號。
它的程式碼可以寫成:
void Print(char n[])
{
 int i;
 for(i=LEN-1; i>0; i--)
   if(n[i]!=0) break;
 for(; i>=0; i--)
   printf("%d", n[i]);
 printf("\n");
}
寫成之後,我們可以先輸入一個約 60 位數的數字,看是不是可以正常印出結果。

二、大數相加
接下來我們來寫一個處理兩個大數相加的題目,接著上一段的程式,我們接下來要寫一個處理相加的函數 Add(),它的做法就跟小學時的加法運算一樣,從個位數開始,一個位數一個位數相加,如果有超過 10 的部分,就把它往前進位。例如:
大數 A
0
1
2
3
4
5
6
7
8
9
大數 B
0
1
2
3
4
5
6
7
8
9
相加
0
2
4
6
8
10
12
14
16
18
進位
0
2
4
6
9
1
3
5
7
8
下面的程式碼可以參考看看:
void Add(char a[], char b[], char c[])
{
 int i;
 for(i=0; i<LEN; i++)
   c[i]=a[i]+b[i];
 for(i=0; i<LEN-1; i++) {
   if(c[i]>=10) {
     c[i+1]+=c[i]/10;
     c[i]=c[i]%10;
   }
 }
}
接下來把主程式 main() 改寫成:
void main()
{
 char a[LEN], b[LEN], c[LEN];
 Input(a);
 Input(b);
 Add(a, b, c);
 Print(c);
}

三、#10106 ─ Product
題目:按這裡
說明:每組測試資料有 2 列,分別代表 2 個大數 XY ( 0 <= XY < 10250),輸出 X*Y 的結果。
這一題的大數位數有 250 位,我們原先宣告的 LEN 300 所以已經夠用了。因為乘出來的積的最大位數為原來的兩倍,所以那一行 C[LEN] 要改成 C[LEN*2],而 Print() 函數裡面的 i=LEN-1 也要改成 i=LEN*2-1。接下來,我們要寫一個乘(Multiply)的函數 Mul(),它的做法就跟小學的乘法原理是一樣的,下面我們來看到它的程式碼:
void Mul(char a[], char b[], char c[])
{
 int i, j;
 for(i=0; i<LEN*2; i++)
   c[i]=0;
 for(i=0; i<LEN; i++) {
   for(j=0; j<LEN; j++) {
     c[i+j]+=a[j]*b[i];
     if(c[i+j]>=10) {
       c[i+j+1]+=c[i+j]/10;
       c[i+j]=c[i+j]%10;
     }
   }
 }
}
再把主程式改成:
void main()
{
 char a[LEN], b[LEN], c[LEN*2];
 Input(a);
 Input(b);
 Mul(a, b, c);
 Print(c);
}
最後再改成連續輸入的寫法:
void main()
{
 char a[LEN], b[LEN], c[LEN*2];
 while(1) {
   if(Input(a)) return;
   Input(b);
   Mul(a, b, c);
   Print(c);
 }
}

0
1
2
3
4
5
6
7
8
9
10
0
1
2
3
4
5
6
7
8
9
10
 
1
0
0
0
0
0
0
0
0
0
1
 
0
0
1
2
3
4
5
6
7
8
9
 
9
9
9
9
9
9
9
9
9
9
9
 
0
0
1
2
3
4
5
6
7
8
9
1
1
1
1
1
1
1
1
1
1
1
0
 
0
0
0
0
0
1
1
1
1
1
0
1
1
0
0
0
0
0
0
0
0
0
0
 
0
0
2
4
6
9
1
3
5
7
8
9
0
0
0
0
0
0
0
0
0
9
9
0
0
0
0
0
0
0
0
0
9
9
0
0
0
0
0
0
0
0
0
9
9
0
0
0
0
0
0
0
0
0
9
9
0
0
0
0
0
0
0
0
0
9
9
0
0
0
0
0
0
0
0
0
9
9
0
0
0
0
0
0
0
0
0
9
9
0
0
0
0
0
0
0
0
0
9
9
0
0
0
0
0
0
0
0
0
9
9
0
0
0
0
0
0
0
0
0
9
9
0
0
0
0
0
0
0
0
0
9
1
1
1
1
1
1
1
1
1
1
1
0
0
0
0
0
0
0
0
0
0
 
1
0
0
0
0
0
0
0
0
0
0
8
9
9
9
9
9
9
9
9
9
9
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
0
0
9
18
27
36
45
54
63
72
81
0
0
8
16
24
32
40
48
56
64
72
0
0
7
14
21
28
35
42
49
56
63
0
0
6
12
18
24
30
36
42
48
54
0
0
5
10
15
20
25
30
35
40
45
0
0
4
8
12
16
20
24
28
32
36
0
0
3
6
9
12
15
18
21
24
27
0
0
2
4
6
8
10
12
14
16
18
0
0
1
2
3
4
5
6
7
8
9
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1
2
4
6
9
13
18
22
25
26
25
24
20
15
8
 
0
0
0
0
1
5
2
4
1
5
7
8
7
5
0
1
9
0
5
2
1




程式 :

#coding=utf8

initial_value = 'x'
list_length = 100
sample_list1 = [ initial_value for i in range(100)]   #0--99 
sample_list2 = [initial_value]*list_length

initial_value = 0
sample_list3 = [initial_value]*list_length
sample_list4 = [initial_value]*list_length
sample_list5 = [initial_value]*list_length

sample_list6 = [initial_value]*list_length*2    #乘法的積  Product =a * b 

print("40、大數加法,兩個100位數以內的數字相加,列印出結果。")
print("41、大數減法,兩個100位數以內的數字相減,列印出結果。")
print("42、大數乘法,兩個100位數以內的數字相乘,列印出結果。")
print("43、大數除法,兩個100位數以內的數字相除,列印出結果。")
print("===========================================")
print("輸入範例 0123456789=第一位數為0=1億2千3百4拾5萬6千7百8拾9==")
print("===========================================")

print("請輸入 被加數(被減數,被乘數,被除數) =第一位數為0===")

while True:
     b=int(input("請輸入數值 0 <  a  <9  ,a=10離開:"))
     try:
        b= int(b)
       
     except ValueError:
       print ('這是不合法的輸入.  請再輸入一次...')
       continue
        
     if ( b ==0 ):
       break

sample_list1[0]=0

a=1
k=1
while(a != 0):
  while True:
     b=int(input("請輸入數值 0 <  a  <9  ,a=10離開:"))
     try:
        b= int(b)
       
     except ValueError:
       print ('這是不合法的輸入.  請再輸入一次...')
       continue
        
     if ( b >=0 and b<=10):
       break
      
  if b==10:
     a=0
     break

  if (k>=100) :
     a=0
     break
    
  sample_list1[k]=b
  k=k+1


j=len(sample_list1)
for i in range(0,k):
     sample_list3[j-(k-i)]=sample_list1[i]

j=len(sample_list1)
for i in range(0,j):
     print(sample_list3[i],end="")
print()
     
print("===========================================")
print("請輸入 加數(減數,乘數,除數)=第一位數為0=========")    

while True:
     b=int(input("請輸入數值 0 <  a  <9  ,a=10離開:"))
     try:
        b= int(b)
       
     except ValueError:
       print ('這是不合法的輸入.  請再輸入一次...')
       continue
        
     if ( b ==0 ):
       break

sample_list2[0]=0

a=1
l=1
while(a != 0):
  while True:
     b=int(input("請輸入數值 0 <  a  <9  ,a=10離開:"))
     try:
        b= int(b)
       
     except ValueError:
       print ('這是不合法的輸入.  請再輸入一次...')
       continue
       
     if ( b >=0 and b<=10):
       break
      
  if b==10:
     a=0
     break

  if (l>=100) :
     a=0
     break
    
  sample_list2[l]=b
  l=l+1


j=len(sample_list1)
for i in range(0,l):
     sample_list4[j-(l-i)]=sample_list2[i]

j=len(sample_list1)
for i in range(0,j):
     print(sample_list4[i],end="")
print()

#================================

cy=0
j=len(sample_list1)-1

for i in range(j,-1,-1):
   sample_list5[i]= sample_list3[i]+sample_list4[i]+cy
   cy= sample_list5[i]//10
   sample_list5[i]=sample_list5[i]%10

print("===========================================")
print("相加結果==>",end="")

#判斷 被加數或加數的 長度 哪一個 長


if k>=l:
   m=k
else:
   m=l
   
j=len(sample_list1)-1
for i in range((j-m),j+1):     
     print(sample_list5[i],end="")

print()
#================================

cy=0
m=len(sample_list1)-1

for i in range(m,-1,-1):
  for j in range(m,-1,-1):
       sample_list6[i+j]=sample_list6[i+j]+sample_list3[j]*sample_list4[i]
       if sample_list6[i+j]>=10 :
           sample_list6[i+j-1]=sample_list6[i+j-1]+sample_list6[i+j]//10
           sample_list6[i+j]=sample_list6[i+j]%10

print("===========================================")
print("相乘的結果==>",end="")

if k>=l:
   m=2*k
else:
   m=2*l
j=len(sample_list6)-1
for i in range(j-m,j):     
     print(sample_list6[i],end="")

print()



結果:

================= RESTART: D:\程式語言 Python 入門\50題\Ex50-40.py =================
40、大數加法,兩個100位數以內的數字相加,列印出結果。
41、大數減法,兩個100位數以內的數字相減,列印出結果。
42、大數乘法,兩個100位數以內的數字相乘,列印出結果。
43、大數除法,兩個100位數以內的數字相除,列印出結果。
===========================================
輸入範例 0123456789=第一位數為0=1億2千3百4拾5萬6千7百8拾9==
===========================================
請輸入 被加數(被減數,被乘數,被除數) =第一位數為0===
請輸入數值 0 <  a  <9  ,a=10離開:0
請輸入數值 0 <  a  <9  ,a=10離開:1
請輸入數值 0 <  a  <9  ,a=10離開:2
請輸入數值 0 <  a  <9  ,a=10離開:3
請輸入數值 0 <  a  <9  ,a=10離開:4
請輸入數值 0 <  a  <9  ,a=10離開:5
請輸入數值 0 <  a  <9  ,a=10離開:6
請輸入數值 0 <  a  <9  ,a=10離開:7
請輸入數值 0 <  a  <9  ,a=10離開:8
請輸入數值 0 <  a  <9  ,a=10離開:9
請輸入數值 0 <  a  <9  ,a=10離開:10
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123456789
===========================================
請輸入 加數(減數,乘數,除數)=第一位數為0=========
請輸入數值 0 <  a  <9  ,a=10離開:0
請輸入數值 0 <  a  <9  ,a=10離開:1
請輸入數值 0 <  a  <9  ,a=10離開:2
請輸入數值 0 <  a  <9  ,a=10離開:3
請輸入數值 0 <  a  <9  ,a=10離開:4
請輸入數值 0 <  a  <9  ,a=10離開:5
請輸入數值 0 <  a  <9  ,a=10離開:6
請輸入數值 0 <  a  <9  ,a=10離開:7
請輸入數值 0 <  a  <9  ,a=10離開:8
請輸入數值 0 <  a  <9  ,a=10離開:9
請輸入數值 0 <  a  <9  ,a=10離開:10
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000123456789
===========================================
相加結果==>00246913578
===========================================
相乘的結果==>00015241578750190521
>>>

沒有留言:

張貼留言

2024_09 作業3 以Node-Red 為主

 2024_09 作業3  (以Node-Red 為主  Arduino 可能需要配合修改 ) Arduino 可能需要修改的部分 1)mqtt broker  2) 主題Topic (發行 接收) 3) WIFI ssid , password const char br...