↓のプログラムが、なぜ実行結果のsumが1ではなく1.000054や9.99999999999906e-001、9.9999999999990619e-001といった答えにになってしまうのでしょうか?
10000のところを512でやった場合は普通に1と出力されたのに・・・
#include <stdio.h>
int main(void){
int i;
float f;
double d;
f = 0.0;
for(i = 0; i<10000; i++) {
f += 1.0/10000;
}
printf("float: n=%d sum=%f\n", 10000, f);
d = 0.0;
for(i = 0; i<10000; i++) {
d += 1.0/10000;
}// end for
printf("double:16.14e: n=%d sum=%16.14e\n", 10000, d);
printf("double:18.16e: n=%d sum=%18.16e\n", 10000, d);
return 0;
}
実行結果
float: n=10000 sum=1.000054
double:16.14e: n=10000 sum=9.99999999999906e-001
double:18.16e: n=10000 sum=9.9999999999990619e-001
続行するには何かキーを押してください . . .
No.2ベストアンサー
- 回答日時:
「打ち切り誤差」と言ってるので、2進⇔10進の変換を有限桁でやろうとすると、誤差が出るのは御存じなのですよね。
floatやdoubleは、内部では 「a * 2^b : ^はべき乗、 a, bは有限範囲の整数」という形で表現されています。
※ 正確にはちょっと違いますが、説明のため、等価なものに変換しています。
1/512= 1 * 2^(-9) です。これは、a=1,b=-9と内部表現との間に誤差は出ません。 誤差が無いので、512回足しても 512 * 2^-9 となり、1 * 2^0 ぴったりになります。
対して, 1/10000 を a * 2^b と表現しようとすると、 a,bともに無限の桁が必要で、有限桁では表現できません。そのため、表現できる範囲で打ち切ります。残りが誤差となります。
この誤差のある状態で加えていくので、どんどん誤差が蓄積されていきます。
それが、その実行結果です。
floatとdoubleで差があるのは、a,bの範囲の違いで、floatの方が取れる範囲が小さいため、その分誤差も大きくなります。
これは大抵のプログラム言語や計算ソフトに共通する問題です。
式を工夫して計算順番を変える(1を10000回足して10000で割ったものでは誤差は出ません)、特定の計算に特化した方法を使う(有理数の範囲で使うなら、内部で整数/整数で表現される「有理数クラス」を用意する)等、誤差対策が必要です。
No.1
- 回答日時:
コンピュータが扱う二進数では整数を全て2のn乗の和で表現できます。
しかし小数の場合は2の-n乗の和で表現できない数値があるため記憶する数値に誤差が生じます。
つまり1/512はちょうど2の-9乗のため誤差なく記憶できます。
しかし1/10000=0.0001は2の-n乗の和で表現できないため誤差が生じます。
試しに2のn乗となる数値で割るようにすればオーバーフローを起こさない限り計算結果は1になるはずです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語: ポインタ 5 2022/06/01 08:33
- C言語・C++・C# プログラミング実行後に表示される値を答えよ #include <stdio.h> void main 4 2022/05/28 10:20
- C言語・C++・C# プログラミング実行後の表示される値を答えよ #include<stdio.h> void main( 7 2022/05/20 00:07
- C言語・C++・C# プログラミングを教えて欲しいです。 配列aは、int a[9]={7,6,12,8,3,5,10,9 4 2022/12/19 23:27
- C言語・C++・C# C言語階乗の総和を求める 2 2023/03/04 23:31
- C言語・C++・C# このプログラミングの問題を教えてほしいです。 キーボードからデータ数nとn個のデータを入力し、平均値 3 2022/12/19 22:51
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語でユーザ関数を利用して複素数のべき乗と絶対値の数列を計算するプログラムが作りたいです。 3 2023/01/29 22:13
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ExcelのINT関数の計算結果がお...
-
c languageで 簡単な質問があ...
-
C言語プログラミングにて、arct...
-
VB6.0での小数点の扱いについて
-
有効数字について 以前質問をし...
-
CRCの計算方法について
-
VB.net Double と...
-
10進数での「25」が2進数では「...
-
16進数 加算 減算 C言語
-
PICで小数点の演算
-
BCD・HEX・BINについて
-
255の2の補数、B'00000001'が-...
-
16進数とかわからないです
-
浮動小数点演算を固定小数点演...
-
C言語で確実に論理右シフトをす...
-
VBAでミリ秒まで出力する方法
-
加算と減算で乗算と除算を表現...
-
VBAでの割り算の余りの求め方
-
”/”を使わずに割り算したいんで...
-
O(n log n)について2
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
O(n log n)について2
-
三角比の俯角の計算
-
c languageで 簡単な質問があ...
-
16進数 加算 減算 C言語
-
ExcelでPC(パソコン)によって...
-
VB.net Double と...
-
”/”を使わずに割り算したいんで...
-
ExcelのINT関数の計算結果がお...
-
有効数字について 以前質問をし...
-
floatの有効桁数
-
三菱シーケンサ(Aシリーズ)で...
-
距離から緯度経度を求める方法
-
VBAでミリ秒まで出力する方法
-
EXCELの関数"STDEV(標準偏差)"...
-
除算を使わずに10で割りたい。
-
C言語プログラミングにて、arct...
-
VB6.0での小数点の扱いについて
-
VBAでの割り算の余りの求め方
-
255の2の補数、B'00000001'が-...
-
変換指定子%22-16gの表示...
おすすめ情報