数値計算講義 第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 法と 割り 算を 避け る 工夫を 組み合わせた 方法に よ れば , 多倍長数同士の除算を 使わずに 計算でき る .]
© Copyright 2025 Paperzz