• 検索結果がありません。

計算機言語 I 第 13 回 浮動小数点数と数学関数

N/A
N/A
Protected

Academic year: 2021

シェア "計算機言語 I 第 13 回 浮動小数点数と数学関数"

Copied!
5
0
0

読み込み中.... (全文を見る)

全文

(1)

計算機言語 I 第 13 回 浮動小数点数と数学関数

この講義資料は

,

次の場所にあります

.

http://www.math.u-ryukyu.ac.jp/~suga/gengo/2018-1/13.pdf

1

浮動小数点数

科学技術計算においては

,

小数点付きの数の計算が通常になります

.

また

,

自然界にある定数には

,

アボガド ロ数のような大きな数や

,

プランク定数のように

0

にとても近い数があります

.

これらの数は

, 6.02 × 10

23

6.63 × 10

34

(Js)

のような書かれ方をします

.

これが浮動小数点数といわれるものです

. (

浮動 小数点なので

,

小数点の位置が動くように思えますが

,

むしろ

,

小数点の場所は固定されている

,

対義語として

,

固定小数点数 というのがあるのですが

,

こちらは小数点の場所が動く

.) 6.02 × 10

23において

, 6.02

を仮数部

, 10

23を指数部 と言います

.

人間の都合で

,

上の数は

10

進法になっていますが

,

今のコンピュータでは

,

仮数部

,

指数部ともに

2

進法になっています

(

過去には

, 2

進でないものもあったらしい

).

コンピュータは計算機であり

,

そもそもこのような数を計算する目的で開発されました

.

現在のコンピュータはディジタルですので

,

数学のような連続的な実数を扱うことはできません

.

したがっ

,

浮動小数点数も有限の桁数と範囲を持つ数体系となっています

.

ただし

,

浮動小数点型は整数型と違い

,

算結果の桁あふれ

(overflow,

結果の絶対値が

,

扱える範囲を越える

),

桁落ち

(underflow,

結果の精度が絶対値 の最小数より小さくなる

)

などを検知する仕組み

,

および

,

最後の桁の

4

捨5入に備えた計算などをサポート しています

.

C

における浮動小数点数型

現在の

C

コンパイラでは

, float, double, long double

の浮動小数点が扱えます

.

これらの精度は処理系 依存で

,

float

のビット幅

double

のビット幅

long double

のビット幅 が規格として定めらています

.

これらのうち

, float, double

,

下にある

IEEE-754

*1 の規格が

de facto Standard(

デファクトスタン ダード

,

事実上の標準

)

です

.

下の表で仮数部が

22+1

ビットの意味は

, 2

の補数を利用するため

, 1

ビットが符 号を表すからです

.

指数部は

2

の補数ではなく

,

符号ビットを使います

.

詳しく知りたい人は

,

ネットなり

,

*1The Institute of Electrical and Electronics Engineers

(2)

値解析の本なりを調べてください

.

フォーマット ビット幅 仮数部

(2

)

精度

(10

進換算

)

float IEEE-754

単精度

32

ビット

22+1

ビット

7

桁 

double IEEE-754

倍精度

64

ビット

52+1

ビット

16

long double

IEEE-754

4

倍精度

(128

ビット

)

だったり

, 80

ビット

(

拡張倍精度

)

だったりで

,

処理 系により様々です

.

この講義で用いる処理系は

, 80

ビットのようです

.

浮動小数点数の計算

(a × 10

b

) × (c × 10

d

) = ac × 10

b+d

ですから

,

浮動小数点数の積

(

)

,

仮数部の積

(

)

と指数部の指数の和

(

)

に分解して計算できます

.

たがって

,

仮数部

,

指数部を取り出してきて

,

それぞれに対して必要な演算を施せば良いことがわかります

.

(

)

,

少し面倒になります

.

例えば

, 1.0 + 2.0E-2 = 1.00 + 0.02 = 1.02

ですから

,

指数部の値を一致させて

,

絶対値の小さい方をその分桁を右にずらした後

,

仮数部の和

(

)

を計算 します

.

ずらす桁数は

,

指数部の差に一致することに注意してください

.

桁をずらす際に

,

小さい方の小数部分 の下位の桁は

,

保持することができなくなるので

,

通常は

, 4

5

入されます

.

このような計算で発生する誤差 を丸め誤差と言います

.

ところで

,

上は

10

進法で計算しましたが

,

コンピュータでは指数部仮数部ともに

2

進法で

,

そうすることに より

, 10

進法と計算のアルゴリズムは同じになります

.

さて上のような計算をするには

,

「仮数部

,

指数部を取り出す」という操作と

,

「仮数部の桁をずらす」とい う操作が必要になります

.

これらの操作を実現しているのが

,

教科書

p. 188

から

p. 193

に書かれている

,

「ビット単位の論理演算」と「シフト演算」です

.

多くのプログラミング言語では

,

このような操作をすること

,

あまり想定してません

.

通常のプログラミングで

,

このような操作をすることはほとんどないからです

. C

OS

の開発言語として作られたため

,

このような操作が簡単にできるようになっています

.

ビット単位の論理演算は

,

各ビットで

,

論理和

,

論理積

,

排他的論理和

,

否定

(0, 1

の反転

)

を計算するもので

.

それらの定義の意味は

, (

排他的論理和以外は

)

数理の皆さんには

,

解説をする必要はないでしょう

.

例えば

, IEEE-754 32

ビット

float

では

,

上位

9

桁が指数部です

.

これを

, 32

ビットの整数型にするには

, 11111111100000000000000000000000=0xff800000

とビット単位の論理積を取る

23

ビット右にシフトする

.

という操作で得られるわけです

.

教科書

p. 189, List 7-6, p.191, List 7-7

を実行してみてください

.

(3)

C

での浮動小数点数の表記

簡単な浮動小数点数は

,

小数点を利用して記述すれば良いのは

,

見たとおりです

.

アボガドロ数のような数の 表記は

,

6.02E23

または

6.02e23

のように

,

指数部の値の前に

E

または

e

を記述します

(exponent

e).

上のように記述した浮動小数点数は

, double

型とコンパイラは解釈します

. float

型と解釈させるには

,

最後に

F

または

f

をつけて

, 6.02e23f

のように記述し

, long double

と解釈させるときは

,

最後に

L

または

l

をつけて

, 6.02e23l

のように記述し ます

.

以前にも述べましたが

,

現在では

,

特別なことがない限り浮動小数店型は

double

を利用します

.

現在の多 くのコンピュータでは

, dobule

型が最も早く計算できるように

CPU

やライブラリ関数が作られています

.

printf, scanf

printf

での浮動小数点数の表示は

, %f, %e, %E, %g

double

型の表示を意味し

, float

はこれを利用す ると自動的に

double

型にキャストして表示してくれます

. %f

,

絶対値が大きすぎたり小さすぎたりしな い時の表示で

,

桁数指定は例えば

, %3.1f

とすると

, 3

桁で

,

小数点以下が

1

桁という意味になります

. %E, %e

はアボガドロ数のような表示方法です

. %g

, %f

%e

を数値によって適当に使い分けて表示してくれます

. long double

を表示させるには

, %Lf

のように

, L

を付けます

.

scanf

では

, %f

float

型の読み込みになります

. double

型は

, %lf, long double

型は

, %Lf

となり ます

.

2

数学関数ライブラリ

科学技術計算でよく用いられる初等関数

, sin, cos, tan, log

などは

,

数学関数ライブラリというものにまと められています

.

これらの関数を利用するには

,

これらの関数のプロトタイプ宣言が記述されている

, math.h

を読み込んでおく必要があります

.

#include <math.h>

さらに

,

数学関数ライブラリを利用するには

,

コンパイル時にオプション

-lm

をつける必要があります

. -lm

ld (

リンクエディタ

)

に数学関数ライブラリ

/usr/lib/libm.a

をリンクするように指示するオプションです

.

cc list.c -lm

数学関数ライブラリには

, 3

角関数

,

双曲線関数

,

指数関数

,

対数関数などの初等関数以外にも

,

様々な関数が 存在します

.

どのような関数があるかは

, /usr/include/bits/mathcalls.h

を読めばわかります

.

このファ イルは

, /usr/include/math.h

include

されます

.

関数名のルールとして

,

デフォルトは

double

型で

, float

型は最後に

f, long double

型は最後に

l

付きます

.

例えば

, sin

double

型を引数にして

, double

型を返す関数で

,

その

float

型版は

, sinf,

(4)

long double

版は

, sinl

となります

.

教科書

p.201, List 7-10

から

,

教科書

p. 203, List 7-12

までを実行してください

.

平方根を求める関数

sqrt

は数学関数ライブラリにあります

.

浮動小数点型計算における丸め誤差も実感してください

.

演算の優先順位と結合法則

演算の優先順位が

,

教科書

p. 205

に書いてあります

.

数学での

,

和と積の優先順位のようなものが

,

他の 様々な演算に対して

, C

でどのように決まっているかの規則です

.

ただし

,

以前から何度も述べていますが

,

括弧を利用することにより

,

この表を見なくても優先順位がわかる ようにプログラムは書きます

.

この表は

,

他の人が書いたプログラムを読む際には必要になることもあります

.

このような表を利用してコンパクトなプログラムを書くことが好まれた時代が

,

過去にあったからです

.

自分 のプログラムでは

,

この表に頼らなくても動作がわかるように書くとともに

,

過去のプログラムで

,

優先順位が わからない時には

,

この表を利用するというのが

,

正しい使い方です

.

演算の結合性については

,

右結合の部分だけは

,

注意してください

.

特に

,

式は値を持ち

,

その値は左辺値である

.

を利用したプログラムが多くあるからです

.

ライブラリ関数のリンクについて

何もオプションなしのコンパイルでは

,

「標準

C

ライブラリ

(/usr/lib/libc.a)

」だけがリンクされます

.

なぜ数学関数ライブラリがリンクされないかというのは

, C

の開発時期に関係があります

.

当時は

, 2

次記憶装 置もあまり容量がなかったのです

.

実行可能ファイルに全てのライブラリ関数をリンクすると

,

実行可能ファ イルのファイルサイズが大きくなりすぎるのです

.

したがって

,

特に必要としない限り

,

標準ライブラリだけを リンクするようにして

,

ファイルサイズの肥大化を防いだのです

.

その後

,

共有ライブラリの仕組みが開発され

,

ライブラリ関数はその呼び出しを記述しておけば

,

システムに あるライブラリ関数を動的に呼び出すようになりました

.

現在では

,

特に指定をしない限り

,

ライブラリのリン クは共有ライブラリを使うようになります

.

ただし

,

システム起動時に実行するコマンド

(

例えば

,

スクリプトを利用して色々な設定をする

shell

など

)

では

,

共有ライブラリを使えない可能性もあるので

,

必要なライブラリをリンクした実行ファイルを作ること もできます

.

このようなリンクを「静的リンク」と言います

.

レポート問題

教科書

p. 201, List 7-10

,

原点と

(1.0e160, 1.0e160)

との距離を求めるとどのような結果になるか

? (

下の注意も読む

.)

件名

: overflow

上 の よ う な 場 合 で も

overflow

を 起 こ さ ず に 動 作 す る よ う に

,

プ ロ グ ラ ム を 書 き 直 せ

.

た だ し

, long double

を用いないで

, double

型を使うこと

(

下の注意も読む

).

件名

: List7-10.c

Wikipedia, https://ja.wikipedia.org/wiki/IEEE_754

, 118.625

float

型の

2

進表記が書 かれているが

,

この講義での処理系ではどうなっているか

? 118.625

float

型の

2

進表記を出力す るプログラムを書け

.

件名

: IEEE-754.c

(5)

注意

平面上の原点からの距離を計算する関数として

, hypot

という関数が数学関数ライブラリにあります

.

この 関数を利用すると

,

上のレポート問題のようなエラーは起こりません

.

ただし

,

上のレポート問題では

, hypot

を使わないでください

.

整数型計算でも浮動小数点数計算でも

, overflow, underflow

などは意外に面倒な問題です

.

「計算をさせ る」際には

,

このようなことが起こらないように

,

あらかじめ桁数の評価を行うのが通常です

.

参照

関連したドキュメント

サブルーチン SUBROUTINE 名前 (仮引数の列) IMPLICIT NONE 型名,INTENT(IN) :: 入力引数名 型名,INTENT(OUT) :: 出力引数名 型名,INTENT(INOUT)

32b で表現可能な自然数の範囲を求めよ。また

Unix の開発動機が ( 米語の文章の ) 文書処理でしたので , Ascii 文字に対する処理を効率 よくするシステムが要求されました.. この値は ,

exit() は引数値を shell 変数 status に返してプログラム を終了するライブラリ関数です .... /*

のようにする.通常は,double Complex を使うこと.C 言語で実数を扱う場合は double,複素数を扱う 場合は double Complex とするのが無難である..

cat コマンド を使って,ファイルの中身をデ ィスプレ イに表示させる..

一行目は構造体名 complex の定義、2行目は構造体のメンバを示します。ここでは、メンバ名を re と im としました。この例では、complex 構造体は、2つの double 型のメンバ

教科書 p.93, 6.7 節 , 再帰 recursion の補足 再帰とは, 関数の処理の途中で自分自身を関数呼び出しすることです.. ただし, 教科書のHanoiの塔の様に再帰でしか書けないような処理もありますし, 繰り返し処理に変換する