0.1を10回足しても1にならない!?

2進法で計算するコンピュータにおいて、10進法で0.1と表される数値を10回足しても1になりません。
###### 丸め誤差
実際、10進法の0.1は無限級数で
```math
\begin{equation}
0.1=2^{-4}\sum_{i=0}^{\infty}a_i2^{-i}
\text{ where }a_i=\begin{cases}1&\text{ if }&i\equiv0,1\mod4\\0&\text{ if }&i\equiv2,3\mod4\end{cases}
\end{equation}
```
ですが、倍精度浮動小数点数では$i=52$で打ち切ってしまい、
```math
\begin{equation}
0.1=2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-52}+2^{-53}+\dots\right)
\end{equation}
```
更に、$a_{53}=1$を0捨1入して
```math
\begin{equation}\begin{split}
0.1&=2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-52}+2^{-52}\right)\\
&=2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)
\end{split}\end{equation}
```
となります（これを**丸め誤差**といいます）。
- - -
###### 情報落ち
今から、
- 絶対値の大きい方に指数（先頭の$2$の右肩の数）を合わせて足す
- 仮数部（数式の括弧内）の先頭が$2$になれば指数部を+1
- 仮数部に$2^{-53}$が残れば$2^{-52}$に切り上げ、それ以降は切り捨て（０捨１入）
という方針で$0.1+0.1+\dots+0.1$を計算していきます。

まず、これで0.1+0.1を計算すると
```math
\begin{flalign}
0.1+0.1
&=2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-44}+2^{-45}+2^{-48}+2^{-49}+2^{-51}\right)&\\
&+2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-44}+2^{-45}+2^{-48}+2^{-49}+2^{-51}\right)&\\
&=2^{-4}\left(2+1+2^{-3}+2^{-4}+\dots+2^{-43}+2^{-44}+2^{-47}+2^{-48}+2^{-50}\right)&\\
&=2^{-3}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-44}+2^{-45}+2^{-48}+2^{-49}+2^{-51}\right)&
\end{flalign}
```
となります。
- - -
更に計算を進めていきます。
```math
\begin{flalign}
0.1+0.1+0.1&=(0.1+0.1)+0.1&\\
&=2^{-3}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&+2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&=2^{-3}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&+2^{-3}\left(2^{-1}+2^{-2}+2^{-5}+2^{-6}+\dots+2^{-49}+2^{-50}+2^{-52}\right)&\\
&=2^{-3}\left(2+2^{-2}+2^{-3}+2^{-6}+\dots+2^{-47}+2^{-50}+2^{-51}+2^{-52}\right)&\\
&=2^{-2}\left(1+2^{-3}+2^{-4}+2^{-7}+\dots+2^{-48}+2^{-51}+2^{-52}+2^{-53}\right)&\\
&\sim2^{-2}\left(1+2^{-3}+2^{-4}+2^{-7}+\dots+2^{-47}+2^{-48}+2^{-50}\right)&
\end{flalign}
```
- - -
```math
\begin{flalign}
0.1+0.1+0.1+0.1&=(0.1+0.1+0.1)+0.1&\\
&=2^{-2}\left(1+2^{-3}+2^{-4}+2^{-7}+\dots+2^{-47}+2^{-48}+2^{-50}\right)&\\
&+2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&=2^{-2}\left(1+2^{-3}+2^{-4}+2^{-7}+\dots+2^{-47}+2^{-48}+2^{-50}\right)&\\
&+2^{-2}\left(2^{-2}+2^{-3}+2^{-6}+2^{-7}+\dots+2^{-50}+2^{-51}+2^{-53}\right)&\\
&=2^{-2}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}+2^{-53}\right)&\\
&\sim2^{-2}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}+2^{-52}\right)&
\end{flalign}
```
- - -
```math
\begin{flalign}
&0.1+0.1+0.1+0.1+0.1=(0.1+0.1+0.1+0.1)+0.1&\\
&=2^{-2}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&+2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&=2^{-2}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&+2^{-2}\left(2^{-2}+2^{-3}+2^{-6}+2^{-7}+\dots+2^{-50}+2^{-51}+2^{-53}\right)&\\
&=2^{-2}\left(1+2^{-1}+2^{-2}+2^{-3}+\dots+2^{-48}+2^{-49}+2^{-50}+2^{-51}+2^{-51}+2^{-53}\right)&\\
&=2^{-2}\left(2+2^{-53}\right)=2^{-1}\left(1+2^{-54}\right)\sim2^{-1}&
\end{flalign}
```
計算が間違っていなければ、0.1を5回足した結果は0.5に一致しました。
- - -
```math
\begin{flalign}
&0.1+0.1+0.1+0.1+0.1+0.1=(0.1+0.1+0.1+0.1+0.1)+0.1&\\
&=2^{-1}+2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&=2^{-1}\left(1+2^{-3}+2^{-4}+2^{-7}+\dots+2^{-48}+2^{-51}+2^{-52}+2^{-54}\right)&\\
&\sim2^{-1}\left(1+2^{-3}+2^{-4}+2^{-7}+\dots+2^{-48}+2^{-51}+2^{-52}\right)&\\
\end{flalign}
```
- - -
```math
\begin{flalign}
&0.1+0.1+0.1+0.1+0.1+0.1+0.1=(0.1+0.1+0.1+0.1+0.1+0.1)+0.1&\\
&=2^{-1}\left(1+2^{-3}+2^{-4}+2^{-7}+\dots+2^{-48}+2^{-51}+2^{-52}\right)&\\
&+2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&=2^{-1}\left(1+2^{-3}+2^{-4}+2^{-7}+\dots+2^{-48}+2^{-51}+2^{-52}\right)&\\
&+2^{-1}\left(2^{-3}+2^{-4}+2^{-7}+2^{-8}+\dots+2^{-51}+2^{-52}+2^{-54}\right)&\\
&=2^{-1}\left(1+2^{-2}+2^{-3}+2^{-6}+2^{-7}+\dots+2^{-50}+2^{-51}+2^{-54}\right)&\\
&\sim2^{-1}\left(1+2^{-2}+2^{-3}+2^{-6}+2^{-7}+\dots+2^{-50}+2^{-51}\right)&\\
\end{flalign}
```
- - -
```math
\begin{flalign}
&0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1\\&=(0.1+0.1+0.1+0.1+0.1+0.1+0.1)+0.1&\\
&=2^{-1}\left(1+2^{-2}+2^{-3}+2^{-6}+2^{-7}+\dots+2^{-50}+2^{-51}\right)&\\
&+2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&=2^{-1}\left(1+2^{-2}+2^{-3}+2^{-6}+2^{-7}+\dots+2^{-50}+2^{-51}\right)&\\
&+2^{-1}\left(2^{-3}+2^{-4}+2^{-7}+2^{-8}+\dots+2^{-51}+2^{-52}+2^{-54}\right)&\\
&=2^{-1}\left(1+2^{-1}+2^{-4}+2^{-5}+2^{-8}+\dots+2^{-48}+2^{-49}+2^{-52}+2^{-54}\right)&\\
&\sim2^{-1}\left(1+2^{-1}+2^{-4}+2^{-5}+2^{-8}+\dots+2^{-48}+2^{-49}+2^{-52}\right)&\\
\end{flalign}
```
既に、0.1を8倍した値$2^{-1}\left(1+\dots+2^{-51}\right)$と、0.1を8回足した値$2^{-1}\left(1+\dots+2^{-52}\right)$で、$2^{-53}$の誤差が出ていますね。
絶対値の小さい0.1の指数部-4を、絶対値の大きい0.8の指数部-1に合わせた際、仮数部に残った$2^{-54}$が落ちています。これを**情報落ち**といいます。（この現象はすでに発生している）
- - -
```math
\begin{flalign}
&0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1\\&=(0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1)+0.1&\\
&=2^{-1}\left(1+2^{-1}+2^{-4}+2^{-5}+2^{-8}+\dots+2^{-48}+2^{-49}+2^{-52}\right)&\\
&+2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&=2^{-1}\left(1+2^{-1}+2^{-4}+2^{-5}+2^{-8}+\dots+2^{-48}+2^{-49}+2^{-52}\right)&\\
&+2^{-1}\left(2^{-3}+2^{-4}+2^{-7}+2^{-8}+\dots+2^{-51}+2^{-52}+2^{-54}\right)&\\
&=2^{-1}\left(1+2^{-1}+2^{-2}+2^{-5}+2^{-6}+\dots+2^{-49}+2^{-50}+2^{-54}\right)&\\
&\sim2^{-1}\left(1+2^{-1}+2^{-2}+2^{-5}+2^{-6}+\dots+2^{-49}+2^{-50}\right)&\\
\end{flalign}
```
- - -
```math
\begin{flalign}
&0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1\\&=(0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1)+0.1&\\
&=2^{-1}\left(1+2^{-1}+2^{-2}+2^{-5}+2^{-6}+\dots+2^{-49}+2^{-50}\right)&\\
&+2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&\\
&=2^{-1}\left(1+2^{-1}+2^{-2}+2^{-5}+2^{-6}+\dots+2^{-49}+2^{-50}\right)&\\
&+2^{-1}\left(2^{-3}+2^{-4}+2^{-7}+2^{-8}+\dots+2^{-51}+2^{-52}+2^{-54}\right)&\\
&=2^{-1}\left(1+2^{-1}+2^{-2}+2^{-3}+2^{-4}+\dots+2^{-49}+2^{-50}+2^{-51}+2^{-52}+2^{-54}\right)&\\
&\sim2^{-1}\left(1+2^{-1}+2^{-2}+2^{-3}+2^{-4}+\dots+2^{-49}+2^{-50}+2^{-51}+2^{-52}\right)&\\
\end{flalign}
```
残念ながら、0.1を10回足した結果は、1より$2^{-1}\times2^{-52}=2^{-53}$だけ少ないことが分かりました（途中の計算が間違っていなければ）。
- - -
折角なので、足して1になってほしい浮動小数点数の組み合わせで、誤差をチェックしてみましょう。
以下の`sum`関数のテストをするつもりで、テストケースを作成します。
```c
#include <stdarg.h>

/*
 * 入力された浮動小数点数の合計値を返す
 * n : 入力する浮動小数点数の個数
 */
double sum(int n,...){
	va_list ap;
	va_start(ap,n);
	double total=0.0;
	for(int i=0;i<n;i++){
		total+=va_arg(ap,double);
	}
	va_end(ap);
	return total;
}
```
:::note warn
この関数に対して、可変長引数の部分に整数が入力されると、正しく処理されません。`1`ではなく、`1.0`や`(double)1`として渡してください。
:::
- - -
- 答えが1になってほしいテストを実施し、テスト結果を表示する
```c
#include <stdio.h>
#include <stdarg.h>
#include <math.h>

/* 総テストケース数 */
int tests_run=0;

/* 成功したテストケース数 */
int success=0;

/*
 * 答えが1になってほしいテストを実施し、テスト結果を表示する
 * n : 入力する値の個数
 * 可変長引数の部分には合計が1となることが期待される浮動小数点数列を入力する
 */
void test(int n,...){
	va_list ap;
	va_start(ap,n);
	
	//入力された浮動小数点数を配列に格納する
	double A[10] = {0};
	for(int i=0;i<n;i++){
		A[i]=va_arg(ap,double);
		
		//入力値を画面表示
		putchar(i?'+':'$');
		printf("%.1lf",A[i]);
	}
	va_end(ap);
	
	//テスト：合計値を計算する※n以上の添字の値は関数呼び出し先で使われない
	double result=sum(n,A[0],A[1],A[2],A[3],A[4],A[5],A[6],A[7],A[8],A[9]);
	tests_run++;
	
	//誤差をm*2^nの形で出力する
	int exponent;
	double mantissa=frexp(result-1,&exponent);
	printf("=1");
	if(mantissa)printf("%+lf\\times2^{%d}",mantissa*2,exponent-1);
 	else success++;
	printf("$\n");
}
```
- - -
- テストケース
  - 1～24　{0.1,0.2,0.3,0.4}の順列
  - 25～66　小数点以下1桁以下の正の実数値を昇順ソートした数列（絶対値の小さい値から足したほうが精度が上がる）
※#1と#47は重複しています。
```c
void test1(){test(4,.1,.2,.3,.4);}
void test2(){test(4,.1,.2,.4,.3);}
void test3(){test(4,.1,.3,.2,.4);}
void test4(){test(4,.1,.3,.4,.2);}
void test5(){test(4,.1,.4,.2,.3);}
void test6(){test(4,.1,.4,.3,.2);}
void test7(){test(4,.2,.1,.3,.4);}
void test8(){test(4,.2,.1,.4,.3);}
void test9(){test(4,.2,.3,.1,.4);}
void test10(){test(4,.2,.3,.4,.1);}
void test11(){test(4,.2,.4,.1,.3);}
void test12(){test(4,.2,.4,.3,.1);}
void test13(){test(4,.3,.1,.2,.4);}
void test14(){test(4,.3,.1,.4,.2);}
void test15(){test(4,.3,.2,.1,.4);}
void test16(){test(4,.3,.2,.4,.1);}
void test17(){test(4,.3,.4,.1,.2);}
void test18(){test(4,.3,.4,.2,.1);}
void test19(){test(4,.4,.1,.2,.3);}
void test20(){test(4,.4,.1,.3,.2);}
void test21(){test(4,.4,.2,.1,.3);}
void test22(){test(4,.4,.2,.3,.1);}
void test23(){test(4,.4,.3,.1,.2);}
void test24(){test(4,.4,.3,.2,.1);}

void test25(){test(1,1.);}
void test26(){test(2,.1,.9);}
void test27(){test(2,.2,.8);}
void test28(){test(3,.1,.1,.8);}
void test29(){test(2,.3,.7);}
void test30(){test(3,.1,.2,.7);}
void test31(){test(4,.1,.1,.1,.7);}
void test32(){test(2,.4,.6);}
void test33(){test(3,.1,.3,.6);}
void test34(){test(3,.2,.2,.6);}
void test35(){test(4,.1,.1,.2,.6);}
void test36(){test(5,.1,.1,.1,.1,.6);}
void test37(){test(2,.5,.5);}
void test38(){test(3,.1,.4,.5);}
void test39(){test(3,.2,.3,.5);}
void test40(){test(4,.1,.1,.3,.5);}
void test41(){test(4,.1,.2,.2,.5);}
void test42(){test(5,.1,.1,.1,.2,.5);}
void test43(){test(6,.1,.1,.1,.1,.1,.5);}
void test44(){test(3,.2,.4,.4);}
void test45(){test(4,.1,.1,.4,.4);}
void test46(){test(3,.3,.3,.4);}
void test47(){test(4,.1,.2,.3,.4);}
void test48(){test(5,.1,.1,.1,.3,.4);}
void test49(){test(4,.2,.2,.2,.4);}
void test50(){test(5,.1,.1,.2,.2,.4);}
void test51(){test(6,.1,.1,.1,.1,.2,.4);}
void test52(){test(7,.1,.1,.1,.1,.1,.1,.4);}
void test53(){test(4,.1,.3,.3,.3);}
void test54(){test(4,.2,.2,.3,.3);}
void test55(){test(5,.1,.1,.2,.3,.3);}
void test56(){test(6,.1,.1,.1,.1,.3,.3);}
void test57(){test(5,.1,.2,.2,.2,.3);}
void test58(){test(6,.1,.1,.1,.2,.2,.3);}
void test59(){test(7,.1,.1,.1,.1,.1,.2,.3);}
void test60(){test(8,.1,.1,.1,.1,.1,.1,.1,.3);}
void test61(){test(5,.2,.2,.2,.2,.2);}
void test62(){test(6,.1,.1,.2,.2,.2,.2);}
void test63(){test(7,.1,.1,.1,.1,.2,.2,.2);}
void test64(){test(8,.1,.1,.1,.1,.1,.1,.2,.2);}
void test65(){test(9,.1,.1,.1,.1,.1,.1,.1,.1,.2);}
void test66(){test(10,.1,.1,.1,.1,.1,.1,.1,.1,.1,.1);}
```
- - -
- `main`関数
```c
int main(int argc, char* argv[]){
	test1();
	test2();
	test3();
	test4();
	test5();
	test6();
	test7();
	test8();
	test9();
	test10();
	test11();
	test12();
	test13();
	test14();
	test15();
	test16();
	test17();
	test18();
	test19();
	test20();
	test21();
	test22();
	test23();
	test24();
	test25();
	test26();
	test27();
	test28();
	test29();
	test30();
	test31();
	test32();
	test33();
	test34();
	test35();
	test36();
	test37();
	test38();
	test39();
	test40();
	test41();
	test42();
	test43();
	test44();
	test45();
	test46();
	test47();
	test48();
	test49();
	test50();
	test51();
	test52();
	test53();
	test54();
	test55();
	test56();
	test57();
	test58();
	test59();
	test60();
	test61();
	test62();
	test63();
	test64();
	test65();
	test66();
	printf("success...%d/%d\n",success,tests_run);
	return 0;
}
```
- - -
- 出力結果
※`test`関数にてわざと`$`記号付きで出力したものをそのまま貼り付けているので、Markdown記法では数式のように表示されています。

$0.1+0.2+0.3+0.4=1$
$0.1+0.2+0.4+0.3=1$
$0.1+0.3+0.2+0.4=1$
$0.1+0.3+0.4+0.2=1$
$0.1+0.4+0.2+0.3=1$
$0.1+0.4+0.3+0.2=1$
$0.2+0.1+0.3+0.4=1$
$0.2+0.1+0.4+0.3=1$
$0.2+0.3+0.1+0.4=1$
$0.2+0.3+0.4+0.1=1$
$0.2+0.4+0.1+0.3=1$
$0.2+0.4+0.3+0.1=1+1.000000\times2^{-52}$
$0.3+0.1+0.2+0.4=1$
$0.3+0.1+0.4+0.2=1$
$0.3+0.2+0.1+0.4=1$
$0.3+0.2+0.4+0.1=1$
$0.3+0.4+0.1+0.2=1$
$0.3+0.4+0.2+0.1=1-1.000000\times2^{-53}$
$0.4+0.1+0.2+0.3=1$
$0.4+0.1+0.3+0.2=1$
$0.4+0.2+0.1+0.3=1$
$0.4+0.2+0.3+0.1=1+1.000000\times2^{-52}$
$0.4+0.3+0.1+0.2=1$
$0.4+0.3+0.2+0.1=1-1.000000\times2^{-53}$
$1.0=1$
$0.1+0.9=1$
$0.2+0.8=1$
$0.1+0.1+0.8=1$
$0.3+0.7=1$
$0.1+0.2+0.7=1$
$0.1+0.1+0.1+0.7=1$
$0.4+0.6=1$
$0.1+0.3+0.6=1$
$0.2+0.2+0.6=1$
$0.1+0.1+0.2+0.6=1$
$0.1+0.1+0.1+0.1+0.6=1$
$0.5+0.5=1$
$0.1+0.4+0.5=1$
$0.2+0.3+0.5=1$
$0.1+0.1+0.3+0.5=1$
$0.1+0.2+0.2+0.5=1$
$0.1+0.1+0.1+0.2+0.5=1$
$0.1+0.1+0.1+0.1+0.1+0.5=1$
$0.2+0.4+0.4=1$
$0.1+0.1+0.4+0.4=1$
$0.3+0.3+0.4=1$
$0.1+0.2+0.3+0.4=1$
$0.1+0.1+0.1+0.3+0.4=1$
$0.2+0.2+0.2+0.4=1$
$0.1+0.1+0.2+0.2+0.4=1$
$0.1+0.1+0.1+0.1+0.2+0.4=1$
$0.1+0.1+0.1+0.1+0.1+0.1+0.4=1$
$0.1+0.3+0.3+0.3=1$
$0.2+0.2+0.3+0.3=1$
$0.1+0.1+0.2+0.3+0.3=1$
$0.1+0.1+0.1+0.1+0.3+0.3=1$
$0.1+0.2+0.2+0.2+0.3=1$
$0.1+0.1+0.1+0.2+0.2+0.3=1$
$0.1+0.1+0.1+0.1+0.1+0.2+0.3=1$
$0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.3=1$
$0.2+0.2+0.2+0.2+0.2=1$
$0.1+0.1+0.2+0.2+0.2+0.2=1$
$0.1+0.1+0.1+0.1+0.2+0.2+0.2=1$
$0.1+0.1+0.1+0.1+0.1+0.1+0.2+0.2=1$
$0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.2=1$
$0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1=1-1.000000\times2^{-53}$
success...61/66

前半24個のテストケースより、絶対値の小さい値を最後に足してしまうと、誤差が発生しやすくなることが分かります。

###### けた落ち
ついでに、$0.9-0.8$と$0.1$を比較してみたいと思います
```math
\begin{flalign}
0.9
&=2^{-1}\left(1+2^{-1}+2^{-2}+2^{-5}+2^{-6}+\dots+2^{-45}+2^{-46}+2^{-49}+2^{-50}+2^{-52}\right)&\\
0.8
&=2^{-1}\left(1+2^{-1}+2^{-4}+2^{-5}+2^{-8}+\dots+2^{-44}+2^{-45}+2^{-48}+2^{-49}+2^{-51}\right)&\\
0.9-0.8&=2^{-1}\left(2^{-3}+2^{-4}+2^{-7}+2^{-8}+\dots+2^{-47}+2^{-48}+2^{-51}+2^{-52}\right)&\\
&=2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-44}+2^{-45}+2^{-48}+2^{-49}\right)&\\
\end{flalign}
```
一方、
```math
\begin{flalign}
&0.1=2^{-4}\left(1+2^{-1}+2^{-4}+2^{-5}+\dots+2^{-48}+2^{-49}+2^{-51}\right)&
\end{flalign}
```
なので、$0.9-0.8$は$0.1$より$2^{-55}$小さい値となりました。
$0.9-0.8$を計算する際、指数部が元々-1だったのが-4になったことにより、2進法での有効桁数が3桁落ちています。これを**けた落ち**といいます。
```c
#include <stdio.h>
#include <math.h>

int main(int argc, char* argv[]){
	double x=.9;
	x-=.8;
	int exponent;
	double mantissa=frexp(x-.1,&exponent);
	printf("$0.9-0.8=0.1%+lf\\times2^{%d}$\n",mantissa*2,exponent-1);
	return 0;
}
```
実行結果
$0.9-0.8=0.1-1.000000\times2^{-55}$
※実行環境によって、$0.9-0.8$と$0.1$は等しくなることがあります。

- 言語によってはDecimal型のような十進法で扱う型があります。より正確に計算したい場合はそちらを使うようにしましょう。