/******************************************************************** 人工知能パートナーシステム(AIPS)を支える             デジタル回路の世界                      ( ISBN978-4-88359-339-2 ) ********************************************************************* 著者名 萩原良昭 ( hagihara-yoshiaki@aiplab.com )            http://www.aiplab.com/ ********************************************************************* 発行所名 青山社  (info@seizansha.co.jp)            http://www.seizansha.co.jp ********************************************************************** Appendix(1-2-1)    本書の pp.19-23 の補足資料です。    ( 2017.12.9 作成 ) *********************************************************************** **************************************************************************** 本書 ( p.20 ) の 図(1-2-1) は、私のご先祖さまの人数を図にしたものです。 ****************************************************************************  一世代 25 年として 100 年前には 16 人の祖祖母と祖祖父がいたことになります。  200年前では ( 2 の 8 乗 ) = 16 x 16 = 256 人、  300年前では ( 2 の 12 乗 ) = 16 x 16 x 16 = 4096 人、 400年前では ( 2 の 16 乗 ) = 16 x 16 x 16 x 16 = 65536 人 になります。 ****************************************************************************  400年前は徳川幕府が開かれた時代(1603年では、理論上、私のご先祖さまは、   65536 人 になりますが、この数はまだもっともらしい人数に見えますが、      800年前となると、鎌倉幕府が開かれた時代(1192年)となり、   私のご先祖さまは、( 2 の 32 乗 ) = 42 9496 7296 人になりますが、      私のご先祖さまが 42億人もいるわけはありません。。。 **************************************************************************** ( p.20 参照 ) さらに、今から1600年前の古墳時代にもなると、 ( 2 の 64 乗 ) = ( 42 9496 7296 ) の 2 乗              = 1844 6744 0737 0955 1616 人になります。 ****************************************************************************          ( p.21 参照 ) 当用漢字の数をおおよそ、             ( 2 の 12 乗) = 4096 として、     2文字熟語なら、( 2 の 24 乗) = 1677 7216 にもなります。     4文字熟語なら、( 2 の 48 乗) = 284 4749 6671 0656 にもなります。 **************************************************************************** ここで、A[ ]= 4096 と書き、A[4]=4,A[3]=0,A[2]=9,A[1]=6 を意味するとします。 そこでこれから、電卓では簡単に計算できない大きなけた数の数 A[ ] と B[ ] の    たし算 C[ ] = A[ ] + B[ ] と かけ算 D[ ] = A[ ] x B[ ] を    実行するデジタル回路 BigNumber( ) をこれから構築していきます。 まずは、このデジタル回路 BigNumber( ) の入出力関係をしっかりと定義します。      { A[ ], B[ ] } BigNumber( ) --> { C[ ], D[ ] } ;   この BigNumber( ) は、その計算 algorithm を定義した関数名でもあり、  またそれに対応する C 言語の関数 ( function )の名前でもあります。 **************************************************************************** ************************************************************** 大きな数のかけ算回路 a( ) = BigNumber( ) の入出力変数の定義 ************************************************************** This program a( ) computes C[ ] = A[ ] + B[ ] with KA = { A[ ]のけた数 } and KB = { B[ ]のけた数 } ; This program a( ) also computes D[ ] = A[ ] x B[ ] with KC = { C[ ]のけた数 } and KD = { D[ ]のけた数 } ; ************************************************************** A.txt = input data file B.txt = output data file [A.txt] a( ) --> [B.txt] ************************************************************** ●Input data file [A.txt] についての説明です。 最初の等号'='の記号が出るまですべての他の文字は無視されます。   最初の等号'='の記号が出るとその後の数字をA[ ]の値と解釈します。   次の行からまた次の等号'='の記号が出るまですべて無視されます。   次の等号'='の記号が出るとその行の後の数字をB[ ]の値と解釈します。 以下の input data file [A.txt] の行 data はすべて無視されます。 **************************************************************  このprogramは必ず入力data file [A.txt]があらかじめ必要です。     以下に Input data file [A.txt] の例を示します。     ************************************************************** ************************************************** Input data file [A.txt] 本文 p.23 参照    2の 64乗= 1844 6744 0737 0955 1616 から    2の128乗=(1844 6744 0737 0955 1616) x (1844 6744 0737 0955 1616) を計算します。 ************************************************** A[ ] = 1844 6744 0737 0955 1616 B[ ] = 1844 6744 0737 0955 1616 ************************************************** ************************************************************** このprogramの実行で生成される Output data file [B.txt] です。 ************************************************************** ************************************************** Input data file [A.txt] 本文 p.23 参照    2の 64乗= 1844 6744 0737 0955 1616 から    2の128乗=(1844 6744 0737 0955 1616) x (1844 6744 0737 0955 1616) を計算します。 ************************************************** A[ ] = 1844 6744 0737 0955 1616 B[ ] = 1844 6744 0737 0955 1616 ************************************************** ***************************************************** C[ ] = A[ ] + B[ ] ***************************************************** KA = 20 A[ ] = 1844 6744 0737 0955 1616 KB = 20 B[ ] = 1844 6744 0737 0955 1616 KC = 20 C[ ] = 3689 3488 1474 1910 3232 ***************************************************** A[ ]*B[KK] for KK=1 to KB ***************************************************** A[ ]*1 = 18446744073709551616 D[1] = 18446744073709551616 A[ ]*8 = 147573952589676412928 D[2] = 332041393326771929088 A[ ]*4 = 73786976294838206464 D[3] = 3394200909562557497344 A[ ]*4 = 73786976294838206464 D[4] = 34015796071920413179904 A[ ]*6 = 110680464442257309696 D[5] = 340268641183646389108736 A[ ]*7 = 129127208515966861312 D[6] = 3402815539044979857948672 A[ ]*4 = 73786976294838206464 D[7] = 34028229177426093417693184 A[ ]*4 = 73786976294838206464 D[8] = 340282365561237229015138304 A[ ]*0 = 00000000000000000000 D[9] = 3402823655612372290151383040 A[ ]*7 = 129127208515966861312 D[10] = 34028236685250931417480691712 A[ ]*3 = 55340232221128654848 D[11] = 340282366907849546395935571968 A[ ]*7 = 129127208515966861312 D[12] = 3402823669207622672475322580992 A[ ]*0 = 00000000000000000000 D[13] = 34028236692076226724753225809920 A[ ]*9 = 166020696663385964544 D[14] = 340282366920928287944195644063744 A[ ]*5 = 92233720368547758080 D[15] = 3402823669209375113162324988395520 A[ ]*5 = 92233720368547758080 D[16] = 34028236692093843365343618431713280 A[ ]*1 = 18446744073709551616 D[17] = 340282366920938452100180258026684416 A[ ]*6 = 110680464442257309696 D[18] = 3402823669209384631682267022524153856 A[ ]*1 = 18446744073709551616 D[19] = 34028236692093846335269414298951090176 A[ ]*6 = 110680464442257309696 D[20] = 340282366920938463463374607431768211456 ***************************************************** KD = 39 D[ ] = A[ ] x B[ ] = 340 2823 6692 0938 4634 6337 4607 4317 6821 1456 ***************************************************** ***********************************************************************  C[ ] = A[ ] + B[ ] と D[ ] = A[ ] x B[ ] を計算する           C言語の source program です。 ***********************************************************************/ #include int L=0,i,j,k,iE,E,KA,KB,KC,NA,NB,NC,DA,DB,DC,A[200],B[200],C[200]; int ii,jj; int Carry,CC[200],CCC[200]; int KK,KCC,AA[200],BB[200],D[200],KD,KAA,KBB,ND,DD; char c,ch[100]; FILE *fpA,*fpB; char *AAAA="A.txt"; char *BBBB="B.txt"; /*************************************************************************/ int ReadInputA(void) { for (i=0;i<100;i++) {A[i]=0;ch[i]=' ';} /*************** A[ ] の値を読み込みます *******************/ E=-1; NEXTL : L=L+1; /*** A.txt の L 行目を読み込みます ***/ fgets(ch,99,fpA); printf("%s",ch);fprintf(fpB,"%s",ch); /*** '='の記号があるかを、判別します    ***/ /*** '='の記号が出るまで、dataを無視します ***/ for (i=0;i<100;i++) if(ch[i]=='=') E=i ; if(E==-1) goto NEXTL; /*** '='の記号がありました。  ***/ /*** A[ ] の値を取り込みます ***/ KA=0; iE=0; NEXTE: E=E+1; if(ch[E]==' ') {iE=iE+1; if(iE>1) goto NEXTB;goto NEXTE;} if(ch[E]=='0') { KA=KA+1;A[KA]=0; iE=0;goto NEXTE; } if(ch[E]=='1') { KA=KA+1;A[KA]=1; iE=0;goto NEXTE; } if(ch[E]=='2') { KA=KA+1;A[KA]=2; iE=0;goto NEXTE; } if(ch[E]=='3') { KA=KA+1;A[KA]=3; iE=0;goto NEXTE; } if(ch[E]=='4') { KA=KA+1;A[KA]=4; iE=0;goto NEXTE; } if(ch[E]=='5') { KA=KA+1;A[KA]=5; iE=0;goto NEXTE; } if(ch[E]=='6') { KA=KA+1;A[KA]=6; iE=0;goto NEXTE; } if(ch[E]=='7') { KA=KA+1;A[KA]=7; iE=0;goto NEXTE; } if(ch[E]=='8') { KA=KA+1;A[KA]=8; iE=0;goto NEXTE; } if(ch[E]=='9') { KA=KA+1;A[KA]=9; iE=0;goto NEXTE; } iE=iE+1; if(iE>1) goto NEXTB;goto NEXTE; /*************** B[ ] の値を読み込みます *******************/ NEXTB:E=-1; for (i=0;i<100;i++) {B[i]=0;ch[i]=' ';} NEXTLL:L=L+1; /*** 続けて、さらに、A.txt の L 行目を読み込みます ***/ fgets(ch,99,fpA); printf("%s",ch);fprintf(fpB,"%s",ch); /*** '='の記号があるかを、判別します    ***/ /*** '='の記号が出るまで、dataを無視します ***/ for (i=0;i<100;i++) if(ch[i]=='=') E=i ; if(E==-1) goto NEXTLL; /*** '='の記号がありました。  ***/ /*** B[ ] の値を取り込みます ***/ KB=0; iE=0; NEXTEE: E=E+1; if(ch[E]==' ') {iE=iE+1; if(iE>1) goto NEXT;goto NEXTEE;} if(ch[E]=='0') { KB=KB+1;B[KB]=0; iE=0;goto NEXTEE; } if(ch[E]=='1') { KB=KB+1;B[KB]=1; iE=0;goto NEXTEE; } if(ch[E]=='2') { KB=KB+1;B[KB]=2; iE=0;goto NEXTEE; } if(ch[E]=='3') { KB=KB+1;B[KB]=3; iE=0;goto NEXTEE; } if(ch[E]=='4') { KB=KB+1;B[KB]=4; iE=0;goto NEXTEE; } if(ch[E]=='5') { KB=KB+1;B[KB]=5; iE=0;goto NEXTEE; } if(ch[E]=='6') { KB=KB+1;B[KB]=6; iE=0;goto NEXTEE; } if(ch[E]=='7') { KB=KB+1;B[KB]=7; iE=0;goto NEXTEE; } if(ch[E]=='8') { KB=KB+1;B[KB]=8; iE=0;goto NEXTEE; } if(ch[E]=='9') { KB=KB+1;B[KB]=9; iE=0;goto NEXTEE; } iE=iE+1; if(iE>1) goto NEXT;goto NEXTEE; NEXT: for (i=0;i<100;i++) ch[i]=' '; fgets(ch,99,fpA); printf("%s",ch);fprintf(fpB,"%s",ch); for (i=0;i<100;i++) if(ch[i]=='*') return 0; goto NEXT; } /*************************************************************************/ int ADDABC( void ) { /********************************************* CC[ ] = AA[ ] + BB[ ] の計算を実行します。 **********************************************/ i=1;Carry=0; NEXTi : if(i>KAA) goto KAAN; if(i>KBB) goto KBBN; CCC[i]=AA[KAA+1-i]+BB[KBB+1-i]+Carry; Carry=0; if(CCC[i]>9) { CCC[i]=CCC[i]-10; Carry=1;} i=i+1; goto NEXTi; KAAN: if(i>KBB) goto KBBBN; CCC[i]=BB[KBB+1-i]+Carry; Carry=0; if(CCC[i]>9) { CCC[i]=CCC[i]-10; Carry=1; } i=i+1; goto KAAN; KBBBN: CCC[i]=Carry; KCC=KBB; goto FINAL; KBBN: if(i>KAA) goto KAAAN; CCC[i]=AA[KAA+1-i]+Carry; Carry=0; if(CCC[i]>9) { CCC[i]=CCC[i]-10; Carry=1; } i=i+1; goto KBBN; KAAAN: CCC[i]=Carry; KCC=KAA; FINAL: if(Carry==1) KCC=KCC+1; for (i=1;i<=KCC;i++) CC[i]=CCC[KCC+1-i]; return 0;} /*************************************************************************/ int XABC( void ) { /***************************************** CC[ ] = A[ ] * B[KK] を計算します。 ******************************************/ for(i=0;i<200;i++) CCC[i]=0; i=1; NEXTi : if(i>KA) goto KAAN; CCC[i]=A[KA+1-i]*B[KK]+CCC[i]; CCC[i+1]=CCC[i]/10; CCC[i]=CCC[i]-10*CCC[i+1]; i=i+1; goto NEXTi; KAAN: KCC=KA; if(CCC[KA+1]>0) KCC=KCC+1; for(i=1;i<=KCC;i++) CC[KCC+1-i]=CCC[i]; return 0;} /**********************************************************************/ int main(void) { fpA=fopen(AAAA,"r");fpB=fopen(BBBB,"w"); ReadInputA( ); /********************************************************* まず、 C[ ] = A[ ] + B[ ] の計算を実行します。 **********************************************************/ for (i=0;i<100;i++) { AA[i]=A[i];BB[i]=B[i];} KAA=KA;KBB=KB; ADDABC( ); KC=KCC; for (i=0;i<=200;i++) C[i]=0 ; for (i=1;i<=KC ;i++) C[i]=CC[i] ; /*********************************************************/ printf( "\n\n*****************************************************\n\n"); fprintf(fpB,"\n\n*****************************************************\n\n"); printf( " C[ ] = A[ ] + B[ ] "); fprintf(fpB," C[ ] = A[ ] + B[ ] "); printf( "\n\n*****************************************************"); fprintf(fpB,"\n\n*****************************************************"); printf("\n\n KA = %d",KA);fprintf(fpB,"\n\n KA = %d",KA); printf("\n\n A[ ] = "); fprintf(fpB,"\n\n A[ ] = "); j=KC+KC/4-KA-KA/4; for (i=1;i<=j;i++) { printf(" ");fprintf(fpB," "); } NA=KA/4; DA=KA-4*NA; if(DA>0) { for (i=1;i<=DA;i++) { printf("%d",A[i]); fprintf(fpB,"%d",A[i]);} printf(" ");fprintf(fpB," ");} if(NA>0) { for (k=1;k<=NA;k++) { for (j=1;j<=4;j++) { i=j+DA+(k-1)*4 ; printf("%d",A[i]) ; fprintf(fpB,"%d",A[i]);} printf(" ");fprintf(fpB," ");} } printf("\n\n KB = %d",KB);fprintf(fpB,"\n\n KB = %d",KB); printf("\n\n B[ ] = "); fprintf(fpB,"\n\n B[ ] = "); j=KC+KC/4-KB-KB/4; for (i=1;i<=j;i++) { printf(" ");fprintf(fpB," "); } NB=KB/4; DB=KB-4*NB; if(DB>0) { for (i=1;i<=DB;i++) { printf("%d",B[i]); fprintf(fpB,"%d",B[i]);} printf(" ");fprintf(fpB," ");} if(NB>0) { for (k=1;k<=NB;k++) { for (j=1;j<=4;j++) { i=j+DB+(k-1)*4 ; printf("%d",B[i]) ; fprintf(fpB,"%d",B[i]);} printf(" ");fprintf(fpB," ");} } printf("\n\n KC = %d",KC);fprintf(fpB,"\n\n KC = %d",KC); printf("\n\n C[ ] = "); fprintf(fpB,"\n\n C[ ] = "); NC=KC/4; DC=KC-4*NC; if(DC>0) { for (i=1;i<=DC;i++) { printf("%d",C[i]); fprintf(fpB,"%d",C[i]);} printf(" ");fprintf(fpB," ");} if(NC>0) { for (k=1;k<=NC;k++) { for (j=1;j<=4;j++) { i=j+DC+(k-1)*4 ; printf("%d",C[i]) ; fprintf(fpB,"%d",C[i]);} printf(" ");fprintf(fpB," ");} } printf( "\n\n*****************************************************\n\n"); fprintf(fpB,"\n\n*****************************************************\n\n"); /************************************************************** 次に、 D[ ] = A[ ] x B[ ] の計算の実行に入ります。   ここで、B[ ]のけた数を KB としています。              まず、D[1] = A[ ] x B[1] とします。     順次に、KK の値を、KK=2 から KK=KB まで取り、      D[KK] = D[KK-1] x 10 + A[ ] x B[KK] の値を計算します。 D[KB] の値が D[ ] = A[ ] x B[ ] の値となります。       ***************************************************************/ printf( " A[ ]*B[KK] for KK=1 to KB "); fprintf(fpB," A[ ]*B[KK] for KK=1 to KB "); printf( "\n\n*****************************************************"); fprintf(fpB,"\n\n*****************************************************"); KK=1; for (i=0;i<200;i++) D[i]=0;KD=KA; NEXTKK: XABC( ); printf( "\n\n A[ ]*%d = ",B[KK]); fprintf(fpB,"\n\n A[ ]*%d = ",B[KK]); for (i=1;i<=KD-KCC;i++) { printf(" ");fprintf(fpB," "); } for (i=1;i<=KCC;i++) { printf("%d",CC[i]); fprintf(fpB,"%d",CC[i]);} for(i=1;i<200;i++) { AA[i]=0;BB[i]=0; } for(i=1;i<=KCC;i++) AA[i]=CC[i]; KAA=KCC; for(i=1;i<=KD; i++) BB[i]= D[i]; KBB=KD; ADDABC( ); KD=KCC; for (i=0;i<200;i++) D[i]=0 ; for (i=1;i<=KD ;i++) D[i]=CC[i] ; if(KK<10) { printf( "\n\n D[%d] = ",KK); fprintf(fpB,"\n\n D[%d] = ",KK);} if(KK>9) { printf( "\n\n D[%d] = ",KK); fprintf(fpB,"\n\n D[%d] = ",KK);} for (i=1;i<=KD;i++) { printf("%d",D[i]); fprintf(fpB,"%d",D[i]);} KD=KD+1; KK=KK+1; if(KK<=KB) goto NEXTKK; KD=KD-1; printf( "\n\n*****************************************************"); fprintf(fpB,"\n\n*****************************************************"); /**** D[ ] のけた数を KD としています。 ****/ printf("\n\n KD = %d",KD);fprintf(fpB,"\n\n KD = %d",KD); /**** D[ ] = A[ ] x B[ ] の値を出力します。 ****/ printf( "\n\n D[ ] = A[ ] x B[ ] = "); fprintf(fpB,"\n\n D[ ] = A[ ] x B[ ] = "); ND=KD/4; DD=KD-4*ND; if(DD>0) { for (i=1;i<=DD;i++) { printf("%d",D[i]); fprintf(fpB,"%d",D[i]);} printf(" ");fprintf(fpB," ");} if(ND>0) { for (k=1;k<=ND;k++) { for (j=1;j<=4;j++) { i=j+DD+(k-1)*4 ; printf("%d",D[i]) ; fprintf(fpB,"%d",D[i]);} printf(" ");fprintf(fpB," ");} } printf( "\n\n*****************************************************\n\n"); fprintf(fpB,"\n\n*****************************************************\n\n"); fclose(fpA);fclose(fpB); c=getchar( ); if(c=='s') return 0; c=getchar( ); if(c=='s') return 0;return 0; } /***************************** end of source program ******************************/