プログラミング演習I 数値計算における計算精度と誤差

Slides:



Advertisements
Similar presentations
2009/11/10 10 進数と r 進数を相互に変換できる コンピュータのための数を表現できる 2進数の補数を扱える コンピュータにおける負の数の表現を説明で きる コンピュータでの演算方法を説明できる 文字や記号の表現方法を示せる 第7回 今日の目標 § 2.2 数の表現と文字コード.
Advertisements

プログラミング論 第八回数字の計算,整数の入出力. 本日の内容 前回の課題(続き) 前回の課題(続き) 数字の計算をする 数字の計算をする – 加減乗除を行う – インクリメント演算子とデクリメン ト演算子.
平成 27 年 10 月 21 日. 【応用課題 2-1 】 次のビット列は、ある 10 進数を 8 ビット固定小数点表示で表した時の ものです。ただし、小数点の位置は 3 ビット目と 4 ビット目の間としてお り、負数は2の補数で表しています。このとき、元の 10 進数を求めてく ださい。
変数とその種類 変数とは何か? → データ ( 数値 ) を入れておく 箱 1000 変数名とは何か? → 箱に付ける名前 xy 変数名 変数の種類 ( 変数の型 ) → 入れるデータによって箱の種類が異なる int char float double その他たくさん integer (
基本情報技術概論(第2回) 埼玉大学 理工学研究科 堀山 貴史
演算、整数型と浮動小数点型 第3回目 [4月27日、H.16(‘04)] 本日のメニュー 1)前回の課題・宿題 2)ファイルサーバの利用
情報・知能工学系 山本一公 プログラミング演習Ⅱ 第7回 データの基本型 情報・知能工学系 山本一公
演算、整数型と浮動小数点型 第3回[平成16年4月27日(火)]:PN04ー03.ppt 今日の内容 1 復習 2 加減・乗除演算子
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
x y 復習 変数とその種類 変数名 数学の場合 未知数 「変数xに‥を代入し‥」 x = 5 x = 1.3
基礎プログラミング (第五回) 担当者: 伊藤誠 (量子多体物理研究室) 内容: 1. 先週のおさらいと続き (実習)
情報処理Ⅱ 第4回 2007年10月29日(月).
第7回 条件による繰り返し.
岩村雅一 知能情報工学演習I 第8回(後半第2回) 岩村雅一
整数データと浮動小数データ 整数データと浮動小数データの違い.
プログラミング入門2 第2回 型と演算 条件分岐 篠埜 功.
第二回 VB講座 電卓を作ろう.
プログラミング応用 printfと変数.
第10回関数 Ⅱ (ローカル変数とスコープ).
Cプログラミング演習 第7回 メモリ内でのデータの配置.
プログラミング演習I 2003年5月7日(第4回) 木村巌.
プログラミング入門2 第2回 型と演算 条件分岐 篠埜 功.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
高度プログラミング演習 (03).
岩村雅一 知能情報工学演習I 第8回(C言語第2回) 岩村雅一
第7回 条件による繰り返し.
Ibaraki Univ. Dept of Electrical & Electronic Eng.
Ibaraki Univ. Dept of Electrical & Electronic Eng.
プログラミングⅠ 平成30年10月29日 森田 彦.
Cの実行モデル.
四則演算,変数 入力文,出力文,代入文, ライブラリ関数
Ibaraki Univ. Dept of Electrical & Electronic Eng.
浮動小数点型変数で遊ぼっ!              花子.
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
2013年度 プログラミングⅡ ~ 計算してみよう ~.
2015年度 プログラミングⅡ ~ 計算してみよう ~.
整数データと浮動小数データ.
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
情報処理Ⅱ 第2回:2003年10月14日(火).
岩村雅一 知能情報工学演習I 第9回(後半第3回) 岩村雅一
基本情報技術概論(第2回) 埼玉大学 理工学研究科 堀山 貴史
地域情報学 C言語プログラミング 第2回 変数・配列、型変換、入力 2017年10月20日
データの表現 2進数 0と1を使う。 基数(基準になる数)が2. 101(2) かっこで2進数と示すことがある。
x y 復習 変数とその種類 変数とは何か? →データ(数値)を入れておく箱 変数名 変数名とは何か?
オブジェクト指向言語論 第三回 知能情報学部 新田直也.
プログラミングⅡ 第2回.
復習 breakとcontinueの違い int i; for (i = 1; i <= 100; i++) { ・・・処理1・・・・
基本情報技術概論(第13回) 埼玉大学 理工学研究科 堀山 貴史
情報科学 第6回 数値解析(1).
情報処理Ⅱ 第2回 2005年10月14日(金).
情報処理Ⅱ 第2回 2006年10月13日(金).
復習 breakとcontinueの違い int i; for (i = 1; i <= 100; i++) { ・・・処理1・・・・
情報処理Ⅱ 2006年11月24日(金).
情報処理Ⅱ 2005年10月28日(金).
地域情報学 C言語プログラミング 第3回 入力、if文、for文 2016年11月25日
プログラミング入門2 第2回 型と演算 条件分岐 篠埜 功.
cp-15. 疑似乱数とシミュレーション (C プログラミング演習,Visual Studio 2019 対応)
cp-3. 計算 (C プログラミング演習,Visual Studio 2019 対応)
Cプログラミング演習 ニュートン法による方程式の求解.
岩村雅一 知能情報工学演習I 第8回(後半第2回) 岩村雅一
岩村雅一 知能情報工学演習I 第8回(C言語第2回) 岩村雅一
第7章 そろそろ int 以外も使ってみよう! ~データ型 double , bool~
情報処理Ⅱ 第2回 2004年10月12日(火).
地域情報学 C言語プログラミング 第3回 入力、if文、for文 2017年11月1日
四則演算,変数 入力文,出力文,代入文, ライブラリ関数
printf・scanf・変数・四則演算
復習 いろいろな変数型(2) char 1バイト → 英数字1文字を入れるのにぴったり アスキーコード → 付録 int
C言語講座 四則演算  if ,  switch 制御文.
知能情報工学演習I 第10回( C言語第4回) 課題の回答
岩村雅一 知能情報工学演習I 第9回(C言語第3回) 岩村雅一
Presentation transcript:

プログラミング演習I 数値計算における計算精度と誤差 Cプログラミング演習 数値計算における計算精度と誤差

扱える値に範囲がある int 型 int 4バイト C言語では,整数データは int 型などで扱う Microsoft Visual C++ では int  4バイト 扱える値に範囲がある -2147483648 ~ 2147483647 (-231 ~ 231-1) 符号で1ビット,残りで数を表現

オーバーフロー それぞれの型 (int, double など)ごとに「表現可能な範囲」が定まる 計算の途中で「表現可能な範囲」を越えてしまうこと = オーバーフロー

少数点以下切り捨て 整数の演算において除算を行う場合、除算結果の小数点以下は切り捨てられる。 プログラミング演習I 少数点以下切り捨て 整数の演算において除算を行う場合、除算結果の小数点以下は切り捨てられる。 (整数)/(整数)の場合のみ、この小数点以下の切り捨てが行われる。 (整数)/(浮動小数点数)や(浮動小数点数)/(整数)の場合は浮動小数点数型として計算されるので結果に小数点以下の値も含まれる。 異なる型を含む演算では、必要に応じて自動的に型変換が行われる。 予期しない結果を招かないためにも明示的に 型変換をした方がよい。

整数データと浮動小数データの違い 整数データ 浮動小数データ 変数宣言 入力 出力 四則演算 剰余 int kingaku; int en; double teihen; double takasa; 入力 scanf("%d", &kingaku); scanf("%lf", &takasa); 出力 printf("kozeni: %d en\n", en); printf("takasa: %f \n", takasa); 四則演算 四則演算には,+, -, *, / を使う 剰余 en = kingaku%1000; z = fmod(x,y);

1/2 の値は 0 #include "stdafx.h" int _tmain() { int ch; double r; printf("r = %f\n ", r ); ch = getchar(); } このプログラムの実行結果は,直感とは一致しない かも知れない r = 0.000000 右辺に整数の変数しか登場しないので,右辺は整数 の精度で計算される

1.0/2.0 の値は 0.5 #include "stdafx.h" int _tmain() { int ch; double r; printf("r = %f\n ", r ); ch = getchar(); } 「 1 / 2 」 と 「 1.0 / 2.0 」 は,意味が違う r = 0.500000 右辺に浮動小数の変数が登場するので,右辺は浮動小数 の精度で計算される

1/2 と 1.0/2.0 の違い 1/2 は,整数と整数の割り算 1.0/2.0 は,浮動小数と浮動小数の割り算 プログラミング演習I 1/2 と 1.0/2.0 の違い 1/2 は,整数と整数の割り算 文法的には 「2000/30 (値は66) 」と書くのと同じ 1/2 の値は 0 (やはり整数) 1.0/2.0 は,浮動小数と浮動小数の割り算 1.0/2.0 の値は 0.5 (浮動小数)

0除算 ある数を0で割る(0除算)と、プログラムは異常終了する。 割り算を行う場合は割る数が0でないこ とを調べてから行う。 プログラミング演習I 0除算 ある数を0で割る(0除算)と、プログラムは異常終了する。 調和平均を求める場合、入力データに0が含まれると、0除算が起こり異常終了する。 割り算を行う場合は割る数が0でないこ とを調べてから行う。 入力データが0であることを検知して、調和平均の計算を止めるようする。

プログラミング演習I 浮動小数点数の演算

計算機内での数値の表現 数値の桁数は変数の型によって決まっている。 int型 32ビット (Microsoft Visual C++の場合) 50(10) = 00000000000000000000000000110010(2) int 型

負の数 2の補数表現であらわす。 絶対値を決められたビット数で表す 0、1を反転する 1を加える short int 型の例 (-50) 50(10) = 0000000000110010(2) 0、1を反転する 1111111111001101(2) 1を加える -50(10) = 1111111111001110(2)

浮動小数点数 整数(正または負または0)あるいは小数付きの数 仮数(mantissa)部と指数(exponent)部 0.5 ( = 0.5 × 100) 仮数(mantissa)部と指数(exponent)部 仮数 指数 基数(radix) 仮数の整数の桁は1桁で0以外

10進数の0.1を2進数で表すと… 無限小数になる。 23ビットで表すために、小数第24桁目で0捨 1入をするので、誤差が生じる(丸め誤差) プログラミング演習I 10進数の0.1を2進数で表すと… 無限小数になる。 0.1(10)= 0.0001100110011001100110011001…(2) 1.100110011001100110011001…×2-4(2) 23ビットで表すために、小数第24桁目で0捨 1入をするので、誤差が生じる(丸め誤差) 小数第24桁目 0 01111011 10011001100110011001100 = 9.9999994039535522×10-2 0 01111011 10011001100110011001101 = 1.0000000149011612×10-1 10-9程度の誤差

丸め誤差の集積(情報落ち) 丸め誤差が集まると,誤差が増える 出てくる値は 20000 にならない #include "stdafx.h" int _tmain() { double x; double s; int ch; x = 0.0001; s = 10000; for (int i = 0; i < 100000000; i++) { s = s + x; } printf("1 に 0.0001を100000000回足すと%fになります。\n", s); ch = getchar(); 出てくる値は 20000 にならない

浮動小数点でのループの終了判定 ループの制御を浮動小数点型変数を用いて行う場合は注意が必要。 プログラミング演習I 浮動小数点でのループの終了判定 ループの制御を浮動小数点型変数を用いて行う場合は注意が必要。 変数 x を 0.001 きざみで0~1まで変化させて何かを処理する場合(面積の近似計算など) 継続条件式を x <= 1 としても、1,000 回目のループが実行されるかどうかは確認が必要。 0.001 を 1,000 回加えても丸め誤差の集積で1以外の数になっている可能性がある。 1より小さい場合は処理が実行される。 1より大きい場合は処理が実行されない。 ループ回数で制御することで回避する。

仕様 2次方程式を ax2+bx+c=0 として、係数a、b、cを入力してもらう。 プログラミング演習I 仕様 2次方程式を ax2+bx+c=0 として、係数a、b、cを入力してもらう。 2次方程式の解の公式に従って、浮動小数点数解があるとき、2つの解x1とx2を計算し、その値を出力する。そのときの(ax2+bx+c)の値も表示する。

プログラム double a, b, c, d, x1, x2; printf("Please input a b c : "); scanf("%lf %lf %lf", &a, &b, &c); d = b * b - 4 * a * c; /* 判別式の計算 */ if(d >= 0){ /* 判別式が正のとき、解を計算 */ x1 = (-b + sqrt(d)) / (2.0 * a); x2 = (-b - sqrt(d)) / (2.0 * a); printf("x1 = %17.10e (%17.10e)\n",x1,a*x1*x1+b*x1+c); printf("x2 = %17.10e (%17.10e)\n",x2,a*x2*x2+b*x2+c); } else{ /* 判別式が負のとき、虚数解と表示 */ printf("x1 = 虚数解\n"); printf("x2 = 虚数解\n");

プログラムのテスト 係数の値として下の値を入力した場合の結果を観察すると、 (1 –2 1) 方程式の左辺の値 (1 –1000 1) プログラミング演習I プログラムのテスト 係数の値として下の値を入力した場合の結果を観察すると、 (1 –2 1) x1 = 1.0000000000e+000 (0.0000000000e+000) x2 = 1.0000000000e+000 (0.0000000000e+000) (1 –1000 1) x1 = 9.9999900000e+002 (1.1641532183e-010) x2 = 1.0000010000e-003 (-2.0621060415e-011) (1 –1000000 1) x1 = 1.0000000000e+006 (0.0000000000e+000) x2 = 1.0000076145e-006 (-7.6144923700e-006) (1 –100000000 1) x1 = 1.0000000000e+008 (1.0000000000e+000) x2 = 7.4505805969e-009 (2.5494194031e-001) 方程式の左辺の値 x2の左辺の値が0から離れていく(誤差が大きくなる)

桁落ち 有効数字の桁数が減少すること 先の例の(1 –1000000 1)では… |b| → 0 412 e848000000000 プログラミング演習I 桁落ち 有効数字の桁数が減少すること 先の例の(1 –1000000 1)では… |b| → 0 412 e848000000000 √D → 0 412 e847fffffbce4 差 → 0 412 000000000431c 0 3ec 0c70000000000 正規化 有効な桁が12ビットになる もし桁数が限られていなければ、後ろの0が続く40ビットにも値が入るはず。

桁落ち 絶対値がごく近い2数を足したり引いたりして、結果の絶対値が小さくなるような計算を行うと桁落ちが起こる。 プログラミング演習I 桁落ち 絶対値がごく近い2数を足したり引いたりして、結果の絶対値が小さくなるような計算を行うと桁落ちが起こる。 絶対値が小さくなった分だけ相対誤差が大きくなり、有効数字が減る。 式の変形などで桁落ちを回避すること ができることがある。

2次方程式の解で桁落ちを防ぐ |b|+√D の方だけを使って1つの解を求める。 もう1つの解は、解と係数の関係から求める。 b≧0 の場合 プログラミング演習I 2次方程式の解で桁落ちを防ぐ |b|+√D の方だけを使って1つの解を求める。 b≧0 の場合 b<0 の場合 もう1つの解は、解と係数の関係から求める。

改良版プログラム 解と係数の関係より double a, b, c, d, x1, x2; プログラミング演習I 改良版プログラム double a, b, c, d, x1, x2; printf("Please input a b c : "); scanf("%lf %lf %lf", &a, &b, &c); d = b * b - 4 * a * c; /* 判別式の計算 */ if(d >= 0){ /* 判別式が正のとき、解を計算 */ if(b >= 0) x1 = -(b + sqrt(d)) / (2.0 * a); else x1 = (-b + sqrt(d)) / (2.0 * a); x2 = c / (a * x1); printf("x1 = %17.10e (%17.10e)\n",x1,a*x1*x1+b*x1+c); printf("x2 = %17.10e (%17.10e)\n",x2,a*x2*x2+b*x2+c); } else{ /* 判別式が負のとき、虚数解と表示 */ printf("x1 = 虚数解\n"); printf("x2 = 虚数解\n"); } 解と係数の関係より