2016.02.15
double型のもつ誤差
誤差について
double型で小数点以下の値があるときに誤差が出る可能性があります。
0.8 → 0.799999999999999900000000000000 0.9 → 0.899999999999999900000000000000 1.0 → 0.999999999999999900000000000000
このような誤差が出る理由は、後ほど説明します。
Javaソースコード その1
DoubleError1.java
001 002 003 004 005 006 007 008 009 010 011
public class DoubleError1 { public static void main( String[] args ) { // 変数の宣言 double value; // valueを0.0~1.0で,0.1増やしていく for ( value = 0.0; value <= 1.0; value += 0.1 ) { System.out.println( String.format("%.30f", value ) ); } } }
コンパイル ソースコードが「ANSI」の場合
C:\talavax\javasample>javac -encoding sjis DoubleError1.java
コンパイル ソースコードが「UTF-8」の場合
C:\talavax\javasample>javac DoubleError1.java
実行
C:\talavax\javasample>java DoubleError1
0.000000000000000000000000000000 0.100000000000000000000000000000 0.200000000000000000000000000000 0.300000000000000040000000000000 0.400000000000000000000000000000 0.500000000000000000000000000000 0.600000000000000000000000000000 0.700000000000000000000000000000 0.799999999999999900000000000000 0.899999999999999900000000000000 0.999999999999999900000000000000
0.3の場合、誤差が0.00000000000000004です。非常に小さな値ですが、プログラムの用途にとっては問題となる可能性があります。同様に0.8、0.9、1.0も誤差をもっています。
もう少し、詳しくdoubleの値を見ていきます。
Javaソースコード その2
以下のソースコードDoubleError2.javaは、DoubleError1.javaの値を詳しく見るためにBigDecimalクラスを使っています。BigDecimalクラスは、10進数値を文字列として計算するもので厳密な計算が必要なときに使用するクラスです。
DoubleError2.java
001 002 003 004 005 006 007 008 009 010 011 012 013
import java.math.BigDecimal; public class DoubleError2 { public static void main( String[] args ) { // 変数の宣言 double value; // valueを0.0~1.0で,0.1増やしていく for ( value = 0.0; value <= 1.0; value += 0.1 ) { System.out.println( new BigDecimal( value ) ); } } }
実行結果
コンパイル ソースコードが「ANSI」の場合
C:\talavax\javasample>javac -encoding sjis DoubleError2.java
コンパイル ソースコードが「UTF-8」の場合
C:\talavax\javasample>javac DoubleError2.java
実行
C:\talavax\javasample>java DoubleError2
0 0.1000000000000000055511151231257827021181583404541015625 0.200000000000000011102230246251565404236316680908203125 0.3000000000000000444089209850062616169452667236328125 0.40000000000000002220446049250313080847263336181640625 0.5 0.59999999999999997779553950749686919152736663818359375 0.6999999999999999555910790149937383830547332763671875 0.79999999999999993338661852249060757458209991455078125 0.899999999999999911182158029987476766109466552734375 0.99999999999999988897769753748434595763683319091796875
出力結果の0と0.5以外に誤差があることがわかります。
誤差が出る理由
ここから、誤差が出る理由について考えてみます。
次に、小数部を2進数で表現する方法を説明します。
10進数 | 2n | 2進数 |
---|---|---|
0.5 | 2-1 | 0.1 |
0.25 | 2-2 | 0.01 |
0.125 | 2-3 | 0.001 |
0.0625 | 2-4 | 0.0001 |
0.03125 | 2-5 | 0.00001 |
2.5の2進表現は、
10.1
となります。
5.375の2進表現は、
101.011
となります。
以上です。
関連コンテンツ
数値を2進数で表したときの各桁の「0」と「1」に対して演算を行えます。4種類の演算、AND(論理積)、OR(論理和)、XOR(排他的論理和)、NOT(否定)を詳しく説明しています。
2016.03.26