#include <stdio.h>
#define M 8 // 4*(M-1)=小数点以下の桁数 (10 進表示)
#define N 7 // 4*(N-1)=小数点以下の桁数 (16 進表示)
// M-1≒1.204(N-1) (M, N の関係)
void Add(unsigned a[], unsigned b[]);
void Sub(unsigned a[], unsigned b[]);
void Div(unsigned a[], unsigned d);
void Mul(unsigned a[], unsigned d);
void Dup(unsigned a[], unsigned b[]);
void ATAN(unsigned x[], int m);
int if_zero(unsigned a[]);
void Display(unsigned a[]);
void to_decimal(unsigned a[], unsigned w[]);
void main(){
unsigned x[N];
ATAN(x, 5);
Display(x);
}
// arctan(1/m) を x に格納
void ATAN(unsigned x[], int m){
int i, e;
unsigned m2;
unsigned y[N], z[N];
for(i = 0; i < N; i++){ // 配列 x,y の初期化
x[i] = 0;
y[i] = 0;
}
y[0] = 1;
Div(y, m);
Dup(y, x);
m2 = m*m;
i = 1;
do {
Div(y, m2);
Dup(y, z);
Div(z, 2*i+1);
if( (i & 1) == 0 ){ // i が偶数のとき
Add(x, z);
} else { // i が奇数のとき
Sub(x, z);
}
i++;
e = if_zero(z); // z が 0 でないと -1
} while (e == -1); // z が 0 でない限り継続
}
//足算, a + b を a に代入
void Add(unsigned a[], unsigned b[]){
int i,j;
unsigned x;
for(i = 0; i < N; i++){
x = a[i] + b[i];
if(x <= 0xffff){ // 桁上がりしないとき
a[i] = x;
} else { // 桁上がりするとき
a[i] = x & 0xffff; // x の下位 2 バイト
j = i-1; // 以下桁上がりの操作
while(a[j] == 0xffff){ // 1 加えると更に桁が上がるとき
a[j] = 0;
j--;
}
a[j]++;
}
}
}
//引き算, a - b を a に代入 (但し a>b)
void Sub(unsigned a[], unsigned b[]){
int i,j;
for(i = 0; i < N; i++){
if (a[i] >= b[i]){ // そのまま引けるとき
a[i] = a[i] - b[i];
} else { // 上の桁から借りるとき
a[i] = 0x10000 + a[i] - b[i]; // 1 を上から借りる
j = i-1;
while(a[j] == 0){ // 上の桁が 0 であれば
a[j] = 0xffff; // 更に上から借りる
j--;
}
a[j]--;
}
}
}
//割り算, a/d を a に代入 (d <= 0xffff, 16 進 4桁)
// 上の桁から順番に d で割り算。
void Div(unsigned a[], unsigned d){
int i;
unsigned x, q, res;
res = 0;
for(i = 0; i < N; i++){
res = res << 16; // 上の桁の余りを 16 進で4 桁ずらして
x = a[i] + res; // 加える
q = x/d; // d でわる
a[i] = q; // 商
res = x - q*d; // 余りは下の桁の割り算に加える
}
}
//かけ算, a*d を a に代入 (d <= 0xffff, 16 進 4 桁)
// 下の桁から順番に d をかける。
void Mul(unsigned a[], unsigned d){
int i;
unsigned x, q;
q = 0;
for(i = N-1; i >= 0; i--){
x = a[i]*d + q; // 各桁の d 倍に桁上がりの部分を加える
a[i] = x & 0xffff; // x の下位 2 バイト (16 進 4 桁)
q = x >> 16; // x の上位 2 バイト (16 進 4 桁)
} // 桁上がりの部分
}
//a を b にコピー
void Dup(unsigned a[], unsigned b[]){
int i;
for(i = 0; i < N; i++){
b[i] = a[i];
}
}
// a = 0 のとき 0 を返し、そうでないとき -1 を返す関数
int if_zero(unsigned a[]){
int i, j;
j = 0;
for(i = 0; i < N; i++){
if (a[i] != 0) { // 一箇所でも 0 でないとき
j = -1; // j の値を -1 にする
break;
}
}
return j;
}
// 10 進数に変換して表示
void Display(unsigned a[]){
int i,j;
unsigned w[M];
to_decimal(a, w); // 16 進数 a を 10 進数 w に変換
printf("%4.1u.",w
[0]); // 小数点以上の表示 for(i = 1; i < M; i++){
switch(i%5){
case 1: printf("%4.4u", w
[i
]); // 4 桁ごと表示 break;
case 2:printf("%1.1u %3.3u", w
[i
]/1000, w
[i
]%1000); // 4 桁ごと表示 break;
case 3:printf("%2.2u", w
[i
]/100); // 4 桁ごと表示 if(i
%25==13) printf("\n "); // 10 個表示したとき改行 printf("%2.2u", w
[i
]%100); // 4 桁ごと表示 break;
case 4:printf("%3.3u %1.1u", w
[i
]/10, w
[i
]%10); // 4 桁ごと表示 break;
case 0:printf("%4.4u", w
[i
]); // 4 桁ごと表示 if(i
%25==0) printf("\n "); // 10 個表示したとき改行 }
}
}
// 10 進数への変換
void to_decimal(unsigned a[], unsigned w[]){
int i;
unsigned b[N];
for(i = 0; i < N; i++){
b[i] = a[i];
}
w[0] = b[0];
b[0] = 0;
for(i = 1; i < M; i++){
Mul(b, 10000); // b を 10000 倍して
w[i] = b[0]; // 小数点以上を w[i] に代入
b[0] = 0; // 小数点以上を 0 にする
}
}
I2luY2x1ZGUgPHN0ZGlvLmg+CgojZGVmaW5lIE0gOCAgICAgLy8gNCooTS0xKT3lsI/mlbDngrnku6XkuIvjga7moYHmlbAgKDEwIOmAsuihqOekuikKI2RlZmluZSBOIDcgICAgIC8vIDQqKE4tMSk95bCP5pWw54K55Lul5LiL44Gu5qGB5pWwICgxNiDpgLLooajnpLopCiAgICAgICAgICAgICAgICAvLyBNLTHiiZIxLjIwNChOLTEpICAgICAgICAoTSwgTiDjga7plqLkv4IpCgp2b2lkIEFkZCh1bnNpZ25lZCBhW10sIHVuc2lnbmVkIGJbXSk7CnZvaWQgU3ViKHVuc2lnbmVkIGFbXSwgdW5zaWduZWQgYltdKTsKdm9pZCBEaXYodW5zaWduZWQgYVtdLCB1bnNpZ25lZCBkKTsKdm9pZCBNdWwodW5zaWduZWQgYVtdLCB1bnNpZ25lZCBkKTsKdm9pZCBEdXAodW5zaWduZWQgYVtdLCB1bnNpZ25lZCBiW10pOwp2b2lkIEFUQU4odW5zaWduZWQgeFtdLCBpbnQgbSk7CmludCBpZl96ZXJvKHVuc2lnbmVkIGFbXSk7CnZvaWQgRGlzcGxheSh1bnNpZ25lZCBhW10pOwp2b2lkIHRvX2RlY2ltYWwodW5zaWduZWQgYVtdLCB1bnNpZ25lZCB3W10pOwoKdm9pZCBtYWluKCl7CiAgICB1bnNpZ25lZCB4W05dOwoKICAgIEFUQU4oeCwgNSk7CiAgICBEaXNwbGF5KHgpOwp9Ci8vIGFyY3RhbigxL20pIOOCkiB4IOOBq+agvOe0jQoKdm9pZCBBVEFOKHVuc2lnbmVkIHhbXSwgaW50IG0pewogICAgaW50IGksIGU7CiAgICB1bnNpZ25lZCBtMjsKICAgIHVuc2lnbmVkIHlbTl0sIHpbTl07CiAgICBmb3IoaSA9IDA7IGkgPCBOOyBpKyspeyAgICAgLy8g6YWN5YiXIHgseSDjga7liJ3mnJ/ljJYKICAgICAgICB4W2ldID0gMDsKICAgICAgICB5W2ldID0gMDsKICAgIH0KICAgIHlbMF0gPSAxOwoKICAgIERpdih5LCBtKTsKICAgIER1cCh5LCB4KTsKICAgIG0yID0gbSptOwogICAgaSA9IDE7CiAgICBkbyB7CiAgICAgICAgRGl2KHksIG0yKTsKICAgICAgICBEdXAoeSwgeik7CiAgICAgICAgRGl2KHosIDIqaSsxKTsKICAgICAgICBpZiggKGkgJiAxKSA9PSAwICl7ICAgICAvLyBpIOOBjOWBtuaVsOOBruOBqOOBjQogICAgICAgICAgICBBZGQoeCwgeik7CiAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAgICAgLy8gaSDjgYzlpYfmlbDjga7jgajjgY0KICAgICAgICAgICAgU3ViKHgsIHopOwogICAgICAgIH0KICAgICAgICBpKys7CiAgICAgICAgZSA9IGlmX3plcm8oeik7ICAgICAgICAgLy8geiDjgYwgMCDjgafjgarjgYTjgaggLTEKICAgIH0gd2hpbGUgKGUgPT0gLTEpOyAgICAgICAgICAvLyB6IOOBjCAwIOOBp+OBquOBhOmZkOOCiue2mee2mgogICAgCn0KCi8v6Laz566XLCAgYSArIGIg44KSIGEg44Gr5Luj5YWlCnZvaWQgQWRkKHVuc2lnbmVkIGFbXSwgdW5zaWduZWQgYltdKXsKICAgIGludCBpLGo7CiAgICB1bnNpZ25lZCB4OwogICAgZm9yKGkgPSAwOyBpIDwgTjsgaSsrKXsKICAgICAgICB4ID0gYVtpXSArIGJbaV07CiAgICAgICAgaWYoeCA8PSAweGZmZmYpeyAgICAgICAgICAgIC8vIOahgeS4iuOBjOOCiuOBl+OBquOBhOOBqOOBjQogICAgICAgICAgICBhW2ldID0geDsKICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgLy8g5qGB5LiK44GM44KK44GZ44KL44Go44GNCiAgICAgICAgICAgIGFbaV0gPSB4ICYgMHhmZmZmOyAgICAgIC8vIHgg44Gu5LiL5L2NIDIg44OQ44Kk44OICiAgICAgICAgICAgIGogPSBpLTE7ICAgICAgICAgICAgICAgIC8vIOS7peS4i+ahgeS4iuOBjOOCiuOBruaTjeS9nAogICAgICAgICAgICB3aGlsZShhW2pdID09IDB4ZmZmZil7ICAvLyAxIOWKoOOBiOOCi+OBqOabtOOBq+ahgeOBjOS4iuOBjOOCi+OBqOOBjQogICAgICAgICAgICAgICAgYVtqXSA9IDA7CiAgICAgICAgICAgICAgICBqLS07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYVtqXSsrOwogICAgICAgIH0KICAgIH0KfQoKLy/lvJXjgY3nrpcsICBhIC0gYiDjgpIgYSAg44Gr5Luj5YWlICjkvYbjgZcgYT5iKQp2b2lkIFN1Yih1bnNpZ25lZCBhW10sIHVuc2lnbmVkIGJbXSl7CiAgICBpbnQgaSxqOwogICAgZm9yKGkgPSAwOyBpIDwgTjsgaSsrKXsKICAgICAgICBpZiAoYVtpXSA+PSBiW2ldKXsgICAgICAgICAgICAgICAgICAvLyDjgZ3jga7jgb7jgb7lvJXjgZHjgovjgajjgY0KICAgICAgICAgICAgYVtpXSA9IGFbaV0gLSBiW2ldOwogICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIOS4iuOBruahgeOBi+OCieWAn+OCiuOCi+OBqOOBjQogICAgICAgICAgICBhW2ldID0gMHgxMDAwMCArIGFbaV0gLSBiW2ldOyAgIC8vIDEg44KS5LiK44GL44KJ5YCf44KK44KLCiAgICAgICAgICAgIGogPSBpLTE7CiAgICAgICAgICAgIHdoaWxlKGFbal0gPT0gMCl7ICAgICAgICAgICAgICAgLy8g5LiK44Gu5qGB44GMIDAg44Gn44GC44KM44GwCiAgICAgICAgICAgICAgICBhW2pdID0gMHhmZmZmOyAgICAgICAgICAgICAgLy8g5pu044Gr5LiK44GL44KJ5YCf44KK44KLCiAgICAgICAgICAgICAgICBqLS07CiAgICAgICAgICAgIH0KICAgICAgICAgICAgYVtqXS0tOwogICAgICAgIH0KICAgIH0KfQoKLy/libLjgornrpcsICBhL2Qg44KSIGEg44Gr5Luj5YWlIChkIDw9IDB4ZmZmZiwgMTYg6YCyIDTmoYEpCi8vIOS4iuOBruahgeOBi+OCiemghueVquOBqyBkIOOBp+WJsuOCiueul+OAggp2b2lkIERpdih1bnNpZ25lZCBhW10sIHVuc2lnbmVkIGQpewogICAgaW50IGk7CiAgICB1bnNpZ25lZCB4LCBxLCByZXM7CiAgICByZXMgPSAwOwogICAgZm9yKGkgPSAwOyBpIDwgTjsgaSsrKXsKICAgICAgICByZXMgPSByZXMgPDwgMTY7ICAgICAgICAvLyDkuIrjga7moYHjga7kvZnjgorjgpIgMTYg6YCy44GnNCDmoYHjgZrjgonjgZfjgaYKICAgICAgICB4ID0gYVtpXSArIHJlczsgICAgICAgICAvLyDliqDjgYjjgosKICAgICAgICBxID0geC9kOyAgICAgICAgICAgICAgICAvLyBkIOOBp+OCj+OCiwogICAgICAgIGFbaV0gPSBxOyAgICAgICAgICAgICAgIC8vIOWVhgogICAgICAgIHJlcyA9IHggLSBxKmQ7ICAgICAgICAgIC8vIOS9meOCiuOBr+S4i+OBruahgeOBruWJsuOCiueul+OBq+WKoOOBiOOCiwogICAgfQp9CgovL+OBi+OBkeeulywgYSpkIOOCkiBhIOOBq+S7o+WFpSAoZCA8PSAweGZmZmYsIDE2IOmAsiA0IOahgSkKLy8g5LiL44Gu5qGB44GL44KJ6aCG55Wq44GrIGQg44KS44GL44GR44KL44CCCnZvaWQgTXVsKHVuc2lnbmVkIGFbXSwgdW5zaWduZWQgZCl7CiAgICBpbnQgaTsgCiAgICB1bnNpZ25lZCB4LCBxOwogICAgcSA9IDA7CiAgICBmb3IoaSA9IE4tMTsgaSA+PSAwOyBpLS0pewogICAgICAgIHggPSBhW2ldKmQgKyBxOyAgICAgICAgIC8vIOWQhOahgeOBriBkIOWAjeOBq+ahgeS4iuOBjOOCiuOBrumDqOWIhuOCkuWKoOOBiOOCiwogICAgICAgIGFbaV0gPSB4ICYgMHhmZmZmOyAgICAgIC8vIHgg44Gu5LiL5L2NIDIg44OQ44Kk44OIICgxNiDpgLIgNCDmoYEpCiAgICAgICAgcSA9IHggPj4gMTY7ICAgICAgICAgICAgLy8geCDjga7kuIrkvY0gMiDjg5DjgqTjg4ggKDE2IOmAsiA0IOahgSkKICAgIH0gICAgICAgICAgICAgICAgICAgICAgICAgICAvLyDmoYHkuIrjgYzjgorjga7pg6jliIYKfQoKLy9hIOOCkiBiIOOBq+OCs+ODlOODvAp2b2lkIER1cCh1bnNpZ25lZCBhW10sIHVuc2lnbmVkIGJbXSl7CiAgICBpbnQgaTsKICAgIGZvcihpID0gMDsgaSA8IE47IGkrKyl7CiAgICAgICAgYltpXSA9IGFbaV07CiAgICB9Cn0KCi8vIGEgPSAwIOOBruOBqOOBjSAwIOOCkui/lOOBl+OAgeOBneOBhuOBp+OBquOBhOOBqOOBjSAtMSDjgpLov5TjgZnplqLmlbAKaW50IGlmX3plcm8odW5zaWduZWQgYVtdKXsKICAgIGludCBpLCBqOwogICAgaiA9IDA7CiAgICBmb3IoaSA9IDA7IGkgPCBOOyBpKyspewogICAgICAgIGlmIChhW2ldICE9IDApIHsgICAgICAgICAgICAvLyDkuIDnrofmiYDjgafjgoIgMCDjgafjgarjgYTjgajjgY0KICAgICAgICAgICAgaiA9IC0xOyAgICAgICAgICAgICAgICAgLy8gaiDjga7lgKTjgpIgLTEg44Gr44GZ44KLCiAgICAgICAgICAgIGJyZWFrOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiBqOwp9CgovLyAgMTAg6YCy5pWw44Gr5aSJ5o+b44GX44Gm6KGo56S6CnZvaWQgRGlzcGxheSh1bnNpZ25lZCBhW10pewogICAgaW50IGksajsKICAgIHVuc2lnbmVkIHdbTV07CiAgICB0b19kZWNpbWFsKGEsIHcpOyAgICAgICAgICAgICAgIC8vIDE2IOmAsuaVsCBhIOOCkiAxMCDpgLLmlbAgdyDjgavlpInmj5sKICAgIHByaW50ZigiJTQuMXUuIix3WzBdKTsgICAgICAgICAgLy8g5bCP5pWw54K55Lul5LiK44Gu6KGo56S6CiAgICBmb3IoaSA9IDE7IGkgPCBNOyBpKyspewogICAgICBzd2l0Y2goaSU1KXsKICAgICAgY2FzZSAxOiBwcmludGYoIiU0LjR1Iiwgd1tpXSk7IC8vIDQg5qGB44GU44Go6KGo56S6CiAgICAgICAgYnJlYWs7CiAgICAgIGNhc2UgMjpwcmludGYoIiUxLjF1ICUzLjN1Iiwgd1tpXS8xMDAwLCB3W2ldJTEwMDApOyAvLyA0IOahgeOBlOOBqOihqOekugogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDM6cHJpbnRmKCIlMi4ydSIsIHdbaV0vMTAwKTsgLy8gNCDmoYHjgZTjgajooajnpLoKICAgICAgICBpZihpJTI1PT0xMykgcHJpbnRmKCJcbiAgICIpOyAvLyAxMCDlgIvooajnpLrjgZfjgZ/jgajjgY3mlLnooYwKICAgICAgICAgIGVsc2UgcHJpbnRmKCIgIik7CiAgICAgICAgIHByaW50ZigiJTIuMnUiLCB3W2ldJTEwMCk7IC8vIDQg5qGB44GU44Go6KGo56S6CiAgICAgICAgIGJyZWFrOwogICAgICBjYXNlIDQ6cHJpbnRmKCIlMy4zdSAlMS4xdSIsIHdbaV0vMTAsIHdbaV0lMTApOyAvLyA0IOahgeOBlOOBqOihqOekugogICAgICAgIGJyZWFrOwogICAgICBjYXNlIDA6cHJpbnRmKCIlNC40dSIsIHdbaV0pOyAvLyA0IOahgeOBlOOBqOihqOekugogICAgICAgaWYoaSUyNT09MCkgcHJpbnRmKCJcbiAgICIpOyAvLyAxMCDlgIvooajnpLrjgZfjgZ/jgajjgY3mlLnooYwKICAgICAgICAgZWxzZSBwcmludGYoIiAiKTsgYnJlYWs7CiAgICB9CiAgfQp9CgovLyAgMTAg6YCy5pWw44G444Gu5aSJ5o+bCnZvaWQgdG9fZGVjaW1hbCh1bnNpZ25lZCBhW10sIHVuc2lnbmVkIHdbXSl7CiAgICBpbnQgaTsKICAgIHVuc2lnbmVkIGJbTl07CiAgICBmb3IoaSA9IDA7IGkgPCBOOyBpKyspewogICAgICAgIGJbaV0gPSBhW2ldOwogICAgfQogICAgd1swXSA9IGJbMF07CiAgICBiWzBdID0gMDsKICAgIGZvcihpID0gMTsgaSA8IE07IGkrKyl7CiAgICAgICAgTXVsKGIsIDEwMDAwKTsgICAgICAgICAgICAgIC8vIGIg44KSIDEwMDAwIOWAjeOBl+OBpgogICAgICAgIHdbaV0gPSBiWzBdOyAgICAgICAgICAgICAgICAvLyDlsI/mlbDngrnku6XkuIrjgpIgd1tpXSDjgavku6PlhaUKICAgICAgICBiWzBdID0gMDsgICAgICAgICAgICAgICAgICAgLy8g5bCP5pWw54K55Lul5LiK44KSIDAg44Gr44GZ44KLCiAgICB9Cn0=