数値計算講義 第1 2回 多倍長演算・ 精度保証計算

数値計算講義 第1 2 回
多倍長演算・ 精度保証計算
カ ーネ ン コ
金 子
ア レ ク セイ
晃
[email protected]
[email protected]
http://www.kanenko.com/
多倍長演算
1
通常のプロ グラ ミ ン グ言語でサポート さ れて いる 変数の桁数以上の
精度で計算する こ と .
無限精度演算と か任意精度演算と も いう .
原理: ソ ロ バン を 繋げれば (部屋に 納ま る 限り ) いく ら でも 大き な 桁数で
計算でき る .
i.e. 変数を 繋げれば (メ モリ ーの許す限り ) いく ら でも 大き な 桁数で
計算でき る .
KETA(1)
KETA(2)
KETA(3)
KETA(4)
KETA(5)
任意精度浮動小数の最も 簡単なフ ォ ーマッ ト
正規化さ れた浮動小数の仮数部を 十進4 桁ずつ整数配列に 格納する .
小数点の位置を 冪指数と し て 記憶する .
こ の他に , 全体の符号と 仮数部の桁数を 記憶する 必要がある ので
結局, 多倍長浮動小数 A と は次のよ う な 内容の整数配列 (long) と な る :
A(1)
A(2)
A(3)
A(4)
..
.
···
···
···
···
全体の符号 (±1)
指数部 (十進, 符号付き )
仮数部の現在の長さ (使用し て いる ユニッ ト 数)
仮数部の最初の4 桁 (十進 0 ∼ 9999)
※ C 言語の場合は, 適当な 構造体を 定義すれば , も っ と プロ グラ ム し 易く な る .
多倍長浮動小数の演算
2
加法 小数点の位置を 大き い方の数に 合わせて 加え る
例: 0.1234 × 102 + 0.4323 × 101 のと き ,
= 0.1234 × 102 + 0.04323 × 102
桁揃え 立場に よ り 二つに 分かれる :
(1) 小数点以下4 桁に 精度を 固定し て いる と き ,
こ のと き は, 第2 の数を 丸めて 加え る :
= 0.1234 × 102 + 0.0432 × 102 = 0.1666 × 102
(2) 精度はも う 少し と っ て あり , 二つの数は正確
(i.e. 上記の部分の後ろ に 0 が精度の分だけ 続いて いる )
こ のと き は, 仮数部の長さ を 1 増やし て 続け る :
= 0.1234 × 102 + 0.04323 × 102 = 0.16663000 × 102
A(5) に は 3000 を 入れる のが正し い . 間違え て 3 を 入れる と ,
0.16660003 × 102 ができ て し ま う .
繰り 上がり 処理 加法の結果ある ユニッ ト で5 桁に な っ たら 必要と な る .
繰り 上がり は次々 波及する かも し れな いので, 汎用に 書く のは結構大変.
cf. 全加算器の設計.
最上位のユニッ ト で繰り 上がり が起こ る と , 指数の調整が必要と な る .
例: 0.1234 × 104 + 0.9876 × 104 = 1.1110 × 104 = 0.1111 × 105
4 桁ずつの格納法だと , こ の変更は大変
(すべて のユニッ ト で1 桁のずら し が必要と な る ). な ので, 冪は 4 の倍数と し
= 0.00011110 × 108 でア レ ン ジさ れたも のと し て し ま う のが簡単.
(ただし こ の種の処理が続く と 有効桁数が損な われる と いう 欠点がある .)
減法 同様だが, 引け な い場合は上から 借り て 来る 必要が有る .
3
便法と し て , 負に な っ て も よ いから 対応する 部位から 引いて し ま い,
後で一括ア レ ン ジする と いう 流儀も 有る .
加減算だけ が続く と き は, こ の方が高速, かつ1 万回程度の演算数な ら ,
各ユニッ ト に も 途中結果を 格納する 余裕がある .
実際の計算では, データ は符号付き な ので ,
加法・ 減法のど ち ら を 実行する かは, 第2 オペラ ン ド の符号と 合わせて 決ま る .
答の符号は最上位ユニッ ト が正規化後に も 正に な ら な いと き 反転する .
こ の場合は正規化を やり 直さ ねばな ら な い .
乗法 指数部は単な る 和. 仮数部は基本的に 整数の乗算と 同様
1234
x 5678
例: 0.1234 × 104 * 0.5678 × 108 =0.1234* 0.5678 ×1012
----------右の計算よ り , 仮数部は 0.07006652 と な る .
6170
7404
簡易ア レ ン ジ法の下では,
8638
12
(1) 精度が4 桁に 指定さ れて いる と き は , 答 0.0701 × 10
9872
12
(2) 精度が8 桁以上のと き は, 答 0.07006652 × 10
----------7006652
と なる .
一般に , C = A × B と し , A の仮数の第 k ユニッ ト を Ak と 記せば
k
X
(Aj × Bk−j+1 の上位4 桁 + Aj × Bk−j の下位4 桁)
Ck =
j=1
と な る (ただし , 右辺で添字が範囲外と な っ た因子は 0 と みな す .)
特に , 中央付近のユニッ ト では総ユニッ ト 数程度の加算が生ずる .
よ っ て 乗算結果は一回毎に ア レ ン ジする のがよ い .
0. oooo oooo oooo oooo oooo
+
0. oooo oooo oooo
0.
oooo
oooo
oooo
oooo oooo
oooo
oooo
oooo
除法 指数部は引き 算.
4
仮数部の除法は仮商を 立て る 小学生の筆算式に やればでき る が , 低速.
反復法, 特に Newton 法の援用な ど , 種々 の工夫が行われて いる が ,
いずれに し て も 他の演算に 比し て 非常に 時間がかかる .
組み込み函数の実装 単精度や倍精度で sqrt, exp, sin, cos, log な ど の
組み込み函数がど のよ う に 実装さ れて いる かを 調べ , 真似を する .
チュ ーニン グが進みすぎて いる も のは真似ができ な いので , 基本に 帰る .
例:
sqrt(x) Newton 法を 適用し た通常のラ イ ブラ リ 函数の実装法が
そ のま ま 使え る . し かも , 割り 算を 避け た工夫が多倍長では非常に 有効.
exp(x) 概算で exp(y)× 10n , −3 < y < 0 の形に する :
x
n=⌈
⌉, y = x − n log 10,
log 10
exp(y) は Taylor 展開で求める .
通常の倍精度浮動小数用ラ イ ブラ リ では , 同様に 2 冪を 括り 出し た後,
exp(y) の計算に は, 倍精度が保証さ れた複雑な 係数の近似多項式な ど が
使われる が , そ れは倍精度を 越え たら 使え な い :
oo
Q 数値計算の中に は, 函数近似法と いう ト ピ ッ ク がある .
C++ によ る 多倍長演算の実装
5
多倍長浮動小数のク ラ ス infprec を 定義し , そ の上の演算を 実装する と
演算子を オーバーロ ード でき る .
多倍長数に 対する 組み込み函数も 定義し て 追加でき る .
等の C++ の特徴が使え る .
こ の結果, 倍精度浮動小数に 対する のと ほと んど 同じ 表記で
多倍長数での計算が可能と な る :
infprec A, B, C;
...
C=A*B-3*A+2*B/A;
....
高速に 実装する に は, 多倍長浮動小数型の引数のコ ピ ーが
頻発し な いよ う に , サブルーチン 間のデータ の受渡し の書き 方を
工夫する 必要がある .
ただの配列 A な ら , 普通に 引数に 書け ば , A のア ド レ ス が渡る (参照渡し ).
し かし , A が infprec 構造体宣言さ れて いる と , デフ ォ ールト では A の内容が
コ ピ ーさ れて サブルーチン に 渡さ れる .
こ れを 防ぐ に は,
void sub(infprec &A){
......
のよ う な 書き 方で , 参照渡し を 宣言する と よ い .
(ポイ ン タ ーではな いので , 指すア ド レ ス は変化せず, 安全.)
更に , A の内容を sub の中で変更さ れたく 無い場合は,
void sub(const infprec &A){
......
と する と , ア ド レ ス 参照な のに sub の中で A の要素の値が修正不可能と な る .
oo
Q C 言語流に infprec 宣言を ポイ ン タ で行う こ と も 可能.
こ のと き は, 生成・ 破壊演算子でメ モリ を 確保, 開放する よ う に 書く .
ま た , 構造体の内部を private にし て C++のセキュ リ ティ 機能を 使う べき である .
既存の多倍長演算シ ス テム
6
UBASIC 老舗だが , X86 (特に 昔の NEC PC) のア セ ン ブラ で
書かれて おり , 著者に Windows への移植の意志が無かっ たので ,
今は使われな い .
PARI ボルド ー大で開発さ れ C 言語で書かれた , 主に 整数論の計算用
ツ ールだが , 初等函数の多倍長浮動小数演算も サポート .
libpari.a の形でラ イ ブラ リ と し て も 提供さ れて おり , こ の中の函数を
自分のプロ グラ ム に リ ン ク し て 使え る 他, ソ ース が公開さ れて いる ので ,
必要な 部分を 取っ て 来て 自分のプロ グラ ム に 取り 込んだり も でき る .
(Risa/Asir も 多倍長演算に こ れを 利用し て いる .)
GMP GNU MultiPrecision library. gcc 用のラ イ ブラ リ と し て ,
2000 年頃から 出て いる .
今後はフ リ ーの多倍長演算ラ イ ブラ リ の主流に な る と 思われる
そ の他個人の作品 小生を 含めて 多く の人が作っ て 個人的に 使っ て いる .
最近のお勧め: exflib
http://www-an.acs.i.kyoto-u.ac.jp/~fujiwara/exflib/
数式処理ソ フ ト に組み込ま れた多倍長演算機能 主な 数式処理ソ フ ト
Mathematica, Maple, Macsyma (Maxima), Matlab な ど は, いずれも
そ の中で精度を 任意に 指定し た多倍長浮動小数の演算が可能.
し かし , こ れら を , 自分で書いた C のプロ グラ ム と リ ン ク する のは困難.
GMP の使用例 – C 言語編 (gmptest.c)
7
#include<stdio.h>
#include<stdlib.h>
#include<gmp.h>
/* ヘッ ダフ ァ イ ルの挿入 */
int main(void)
{
int i;
mpf_t s,t;
/* 型宣言 */
mpf_set_default_prec(1000);
mpf_init(s);
/* 変数を 0 で初期化 */
mpf_init_set_str(t,"1e0",10); /* 変数を 1 で初期化 (10 は radix)*/
for (i=1;i<=10000;i++){
mpf_add(s,s,t);
/* s <- s+t */
mpf_div_ui(t,t,i);
/* t <- t*i */
}
mpf_out_str(stdout,10,1000,s); /* 結果の出力 (10 は radix) */
mpf_clear(t);
/* 必須 */
mpf_clear(s);
return 0;
}
コ ン パイ ルは5 階に GMP が標準でイ ン ス ト ールさ れたので次のよ う に する :
gcc gmptest.c -lgmp -o gmptest
ラ イ ブラ リ libgmp.a は C 言語用で , C++ 用は libgmpxx.a
こ のラ イ ブラ リ では, 他に , 整数型 mpz_t, 有理数型 mpq_t を サポート .
指令の詳細はディ レ ク ト リ 内のマ ニュ ア ル gmp-man-4.3.0.pdf を 参照せよ .
π の計算
8
4 4
·
=
古代エジプト 3,
· 3.16
3
223
22
Archimedes
<π<
(内接正 96 角形の辺長)
71
7
22
157
3927
劉徽 (3 世紀)
= 3.1428571 · · · ,
= 3.14,
= 3.1416
7
50
1250
22
355
祖沖之( 5 世紀) 約率
, 密率
= 3.14159292 · · · ,
7
113
3.1415926 < π < 3.1415927
Āryabhat.a (イ ン ド , 5 世紀) 3.1416
355
Adriaan Anthoniszoon (1527–1607) 1585 年に
113
François Viète (Vieta) (フ ラ ン ス , 1540–1603) v
代数学の父.
s
r s
r u
r
∞
Y
π
1 1 1 1u
1 1 1 1 1
2
t
cos n =
=
+
+
+
···
公式
π
2
2 2 2 2 2 2 2 2 2
n=2
を 用いて 1593 年に π を 小数点以下 9 桁計算.
Ludolph van Ceulen (オラ ン ダ, 1540–1610)
正 262 角形の周長を 用いて 小数点以下 35 桁計算.
関孝和 小数点以下 14 桁
正 215 , 216 , 217 角形の周長を 15 桁ほど 計算し ,
補外に よ り , 14 桁を 正し く 求めた .
単位円に 内接する 正 2n 角形の半周長は
√
π
Ln = 2n sin n , L22 = 2 2.
2
π
π
π
半角公式よ り sin n−1 = 2 sin n cos n
2
2
2 √
1
2 2
Ln−1
L22
√
= n
∴ Ln =
n
π = ··· = Y
Y
π
π 2
cos n
cos k
cos k
2
2
2
k=3
k=2
2
n→∞
−→ π.
= n
Y
π
cos k
2
k=2
π
cos n は半角公式で漸化式が作れる :
2
r
1 1
π
π
π
1
cos n =
+ cos n−1 ,
cos 2 = √
2
2 2
2
2
2
9
正 215
正 216
正 217
今, 正
角形の半辺長: 3.14159264877698566948 · · ·
角形の半辺長: 3.14159265238659134580 · · ·
角形の半辺長: 3.14159265328899276527 · · ·
c1
c2
N 角形の半辺長が c0 +
+ 2 + · · · と いう
N
N
漸近展開を 持つと 仮定し ,
c0 = π が半円周の長さ と すれば ,
c2
c1
3.14159264877698566948 · · · = c0 + 15 + 30 + · · ·
2
2
c1
c2
3.14159265238659134580 · · · = c0 + 16 + 32 + · · ·
2
2
c1
c2
3.14159265328899276527 · · · = c0 + 17 + 34 + · · ·
2
2
こ の三式から c1 , c2 を 消去する と ,
c1
6c0 + 15 + · · · = 8 × 3.14159265328899276527 · · ·
2
− 2 × 3.14159265238659134580 · · · ,
c1
3c0 + 15 + · · · = 4 × 3.14159265238659134580 · · ·
2
− 3.14159264877698566948 · · · ,
8
∴ c0 + · · · = × 3.14159265328899276527 · · ·
3
− 2 × 3.14159265238659134580 · · ·
+ 13 × 3.14159264877698566948 · · ·
= 3.14159265358979323894 · · ·
1
左辺の · · · は 45 のオーダー .
2
cf: 正 231 角形の半辺長: 3.14159265358979323734 · · ·
正 235 角形の半辺長: 3.14159265358979323845 · · ·
10
A. Sharp (1653-1742) 1699
71 桁:
下記公式に よ り 小数点以下
1
1
1
π
1
√
√
6 = Arctan 3 = 3 1 − 3·3 + 5·32 − + · · ·
J. Machin (1680–1751) 1706 下記公式を 導き 100 桁計算:
π
1
= 4Arctan 51 − Arctan
4
239
1
1
1
−
+
− +···
=4
3
5 · 55
5 3 · 5
1
1
1
−
−
+
− +···
239 3 · 2393 5 · 2395
※ Arctan x = x −
x3
3
+
x5
5
− +···
(−1 < x ≤ 1)
松永良弼 1739
小数点以下 49 桁. 下記公式を 導き
利用:
12 ·32
12 ·32 ·52
12
+ 4·6·8·10
+ 4·6·8·10·12·14
+ ···
π = 3 1 + 4·6
W.Shanks 1873 Machin の公式に よ り 小数点以下 707 桁計算
こ の計算があま り に 圧巻だっ たので , 以後電子計算機の発明
ま で誰も 挑戦し よ う と する 者は居な かっ た .
11
Ludolph の計算に ついて , 正 262 角形の半辺長:
3.14159265358979323846264338327950288395418471219027
cf. π の真値:
3.14159265358979323846264338327950288419716939937510
ち ょ う ど 35 桁ま で真値な ので , ど のよ う に 答え たか興味深い!
12
松永の計算に ついて , 松永の級数の値:
70 項ま での和:
3.141592653589793238462643383279502884197169398014488669322
78 項ま での和:
3.141592653589793238462643383279502884197169399375088142023
79 項ま での和:
3.141592653589793238462643383279502884197169399375101484119
80 項ま での和:
3.141592653589793238462643383279502884197169399375104756842
松永は“ · · · 3751 微強 ” と 記し て いる ので ,
実際に は 50 桁計算し たと みて よ いであろ う .
本当に 80 項計算し たのか , そ れと も
関孝和の補外法のよ う な 加速法を 援用し た のか ?
コ ン ビ ュ ータ によ る π の計算
13
1949 世界最初 (?) の電子計算機 ENIAC (1946) で 2037 桁 (70 時間).
Shanks の値の 528 桁以降が誤っ て いる のを 発見
1961 D.Shanks-J.W.wrench IBM 7090 に よ り 10 万桁 (約9 時間)
1967 Guilloud-Dichampt CDC 6600 に よ り 50 万桁 (約 28 時間)
1973 Guilloud-Bouyer CDC 7600 に よ り 100 万桁 (約 23 時間)
1981 三好-金田 FACOM M-200 に よ り 200 万桁 (約 137 時間)
1983 後-金田 HITAC S-810/20 で 1000 万桁( 約 24 時間)
1985 Gosper Symbolics 3670 に よ り 1752 万桁 (約 28 時間? )
1986 Bailey CRAY-2 に よ り 2936 万桁 (約 28 時間)
1988 金田-田村 HITAC S-820/80 で2 億桁( 約 35 時間)
1989 G.V.Chudnovsky IBM-3090 で 10 億桁( 2 ヶ 月? )
1991 G.V.Chudnovsky 自家製計算機で 22 億桁( ? )
1995 高橋-金田 HITAC S-3800/480 で 64 億桁( 約 117 時間)
1996 G.V.Chudnovsky 自家製計算機で 80 億桁( 一週間? )
1997 高橋-金田 HITAC SR2201 で 515 億桁( 約 29 時間)
1999 高橋-金田 HITAC SR8000 で 2000 億桁( 約 37 時間)
2002.12.6 金田 & 日立チーム SR8000/MPP で 1 兆 2411 億桁 (約 600 時間)
ENIAC の計算は Machin の項式を 用いて いたが ,
現在では, 算術幾何平均の改良型を
用いる :
√
2) a0 = a = 1, b0 = b = 1/ 2 を 初項と する 二つの数列を
p
an−1 + bn−1
an =
, bn = an−1 bn−1
2
2an bn
で定める と き , π = lim
n
n→∞
X
2j (a2j − b2j )
1−
j=0
精度保証計算
14
精度保証計算と は, 実数 x を 有限浮動小数で近似する と き ,
x0 < x < x1 と 上下から 挟むこ と に よ り , 最終的な 答の誤差の大き さ を
保証付き で与え る も の .
昔は区間演算と 呼んだ . 実現する に は, 非常に 計算量がかかり ,
非実用的だっ た .
粗い計算だと , 演算の度に 区間がど んど ん大き く な り ,
すぐ に 挟んでも 意味の無いよ う な 大き さ に 区間が広がっ て し ま う .
最近の CPU は切り 捨て , 切り 上げのモード 変更ができ る ので ,
そ れぞれのモード で1 回ずつ同じ 計算を する だけ で , i.e.
普通の計算の2 倍の計算量で精度保証が可能と な る .
う ま く 使う と , 数学の定理の実用的証明の道具と な る
CPU の丸めモード :
通常, CPU は正し い計算値を 維持する ため , 少し 多めの桁で計算し ,
結果を 返すと き に 対応する 変数のフ ォ ーマ ッ ト に 合わせて 丸める .
デフ ォ ールト は四捨五入 Near, i.e.
指定のフ ォ ーマ ッ ト で表現可能な 最も 近い値に 丸める .
こ の他に , 切り 上げ Up, 切り 捨て Down, 0 に 最も 近い値 Tozero, の
計4 種が選択可能.
こ れら は実数の集合 R から 表現可能な 浮動小数の集合 F への写像と し て ,
IEEE754 でき ち んと 規定さ れて いる .
Near(-x)=-Near(x),
15
Up(-x)=-Down(x), Down(-x)=-Up(x),
Tozero
x が表現可能浮動小数な ら
Near Tozero Near
Down Up
Down Up
任意の丸め方 Marume に ついて
Marume(x)=x,
−1
2
1
0
演算 ? ∈ {+, -, *, /} の全て に ついて
Marume(x?y)=Marume(x)?Marume(y)
sqrt ま では IEEE754 に 規定がある が, exp, sin な ど ,
他の組み込み函数に ついて は規定が無いので,
CPU の丸めモード を UP や DOWN に 変え ただけ では,
上下から 挟める かど う かは現状では期待でき な い.
=⇒ 自分で書く か , Matlab な ど のソ フ ト に 組み込ま れたも のを
利用する し かな い .
例: 計算機では 0.1 を 10 回足し て も 1 に な ら な い (cf. 藤代先生の基礎講義),
と いう のを 種々 のモード で実験し て みる .
最近接丸め (四捨五入) 方式 (標準) のと き
s = 1.000000000000000e-01 = 9A 99 99 99 99 99 B9 3F
P
10
i=1 s = 9.999999999999999e-01 = FF FF FF FF FF FF EF 3F
上への丸め (切り 上げ ) 方式を 指定し たと き
s = 1.000000000000000e-01 = 9A 99 99 99 99 99 B9 3F
P
10
i=1 s = 1.000000000000001e+00 = 03 00 00 00 00 00 F0 3F
下への丸め (切り 捨て ) 方式を 指定し たと き
s = 9.999999999999999e-02 = 99 99 99 99 99 99 B9 3F
P
10
i=1 s = 9.999999999999998e-01 = FE FF FF FF FF FF EF 3F
ケ プラ ーの問題 — 数値計算を 証明に用いた最初の例
16
球を 空間に でき る だけ 密に 詰める 方法は,
果物屋さ んがオレ ン ジを 積んでいる やり かただろ う . (Kepler 1611)
不思議な こ と に , 最下層の一段の並べ方が図 a でも 図 b でも ,
そ の後に 無駄無く 積み上げて でき た結果は3 次元的に は同じ に な る !
図 c は William Barlow (1845–1934) に よ る そ の説明図.
図a
図 b
図c
こ れよ り 詰めら れな いこ と を , Kepler が予想し て 以来約 400 年振り に
Thomas C. Hales (1998) が精度保証付き 数値計算に よ り 証明し た .
(F. Tóth が有限個のパラ メ ータ の最小問題に 変換し て いた .
そ の最小解は, Kepler 問題の解の空間充填率を 主要項と する 漸近式を 持つ .
Hales はそ の誤差項を 改良し , そ れを 厳密に 評価する こ と に よ り ,
理論的最小解と Kepler 予想の解が一致する こ と を 示し た . )
現実の CPU での精度保証計算
17
INTEL x86 の場合: (プロ グラ ム 見本 roundx86.c)
CPU のモード を 保持する レ ジス タ ー (CW で表さ れる ) の第 10,11 ビッ ト が
丸めのモード を 制御し て いる . (第 8,9 ビッ ト は精度を 制御. )
下記の函数 (イ ン ラ イ ン ア セ ン ブラ ) は __fldcw, __fnstcw の名前で
fenv.h に 定義さ れて いる ので, こ れを イ ン ク ルード する だけ でも よ い.
void setround(int mode){
__asm __volatile ("fldcw %0" : : "m"(mode))
}
int getround(int *mode)
__asm("fnstcw %0" : "=m" (*(mode)))
return *mode;
}
#define FE_TONEAREST
0x0000
#define FE_DOWNWARD
0x0400
#define FE_UPWARD
0x0800
#define FE_TOWARDZERO
0x0c00
AMD64 互換の 64 ビッ ト マ シン では, 上のデータ は共通だが,
10 バイ ト 長の long double で実験し な いと 差が見え な い.
PowerPC の場合: (プロ グラ ム 見本 roundppc.c)
C 言語用のラ イ ブラ リ 函数が用意さ れて いる .
typedef unsigned long fenv_t;
void fesetenv(const fenv_t *); /* 丸めモード 設定 */
void fegetenv(fenv_t *);
/* 丸めモード 問い合わせ */
#define FE_TONEAREST
0x00000000
#define FE_TOWARDZERO
0x00000001
#define FE_UPWARD
0x00000002
#define FE_DOWNWARD
0x00000003
roundppc.c は現在のイ ン テルマ ッ ク では, コ ン パイ ルし て も 正常に
動かな い. 昔の Power Mac でコ ン パイ ルさ れたバイ ナリ roundppc が,
エミ ュ レ ーショ ン で正し く 動く ので, こ れで PowerPC を 味わっ て く ださ い.
本日の講義内容の自習課題
18
1 Kerosoft 社の多倍長演算ラ イ ブラ リ を 使っ て みる .
inflib.f, infdec.f がラ イ ブラ リ で , exp.f, log.f, tri.f な ど が
そ れを 利用し たプロ グラ ム であ る . コ ン パイ ル例:
g77 -c infdec.f inflib.f
g77 log.f inflib.o infdec.o -o log
./log
2 GMP を 使っ た C プロ グラ ム 例を 実行し て みる .
コ ン パイ ルの仕方は
gcc gmptest.c -lgmp -o gmptest
./gmptest
3 CPU の丸めモード を 変更する 実験を し て みる .
roundx64.c は, gcc で普通に コ ン パイ ルでき る .
roundppc.c の方はコ ン パイ ルでき な いので, roundppc を 実行する だ
け に せよ .
PowerMac を 持っ て いる 人は roundppc.c を 持ち 帰っ て
コ ン パイ ル・ 実行し て みよ .
同様に , 32 ビッ ト の Intel CPU 用の roundx86.c は5 階ではコ ン パイ
ルはでき る が
実行し て も 何も 変わら な い. こ れは, CPU が丸めを 80 ビッ ト でやっ
て いる ため,
64 ビッ ト に 落と し たと き に , みな 同じ 値に な っ て し ま う ためのよ う で
ある .
32 ビッ ト Windows 機を 持っ て いる 人は roundx86.c を 持ち 帰っ て
コ ン パイ ル・ 実行し て みよ .
本日の範囲のプロ グ ラ ム 練習問題
19
問題 12.1 Kerosoft 社の多倍長演算ラ イ ブラ リ を 使っ て
x − cos x = 0 の解を 100 桁近似計算せよ .
問題 12.2 C 言語で次の Machin の級数を 実装し , π を 1000 桁計算せよ :
1
1
(−1)n
−
+
·
·
·
+
+
·
·
·
π = 16
5 3 · 53
(2n + 1) · 52n+1
1
1
1 1
(−1)n
−4
−
+
·
·
·
+
+
·
·
·
.
239 3 2393
2n + 1 2392n+1
[ こ れは次問の多倍長演算ラ イ ブラ リ を 構築し な く て も 単独で解け る .]
問題 12.3 GMP を 利用し て 何か興味を 持っ た数を 100 桁計算し て みよ .
(例え ば , 第5 回の課題に 有っ た sin x = x2 の正の解な ど .)
問題 12.4 多倍長数の加減乗算を
実行でき る ラ イ ブラ リ を C 言語で作れ.
√
そ れを 用いて 2 を 1000 桁計算せよ .
[ 第4 回に 紹介し た Newton 法と 割り 算を 避け る 工夫を 組み合わせた
方法に よ れば , 多倍長数同士の除算を 使わずに 計算でき る .]