浮動小数点数の精度

Go言語 (golang)

以下は私の Go 1.4.1 の環境で実行した結果。

float32の場合

package main

import "fmt"
//import "strings"
//import "math/rand"
//import "time"

func main() {
    var x float32

    x = 1.0 + 1e-7; fmt.Println(x)          // 1.0000001
    x = 1.0 + 1e-8; fmt.Println(x)          // 1
    x = (1.0 + 1e-45) - 1.0; fmt.Println(x) // 1e-45
    x = (1.0 + 1e-46) - 1.0; fmt.Println(x) // 0
    x = 1e38; fmt.Println(x);               // 1e+38
    //x = 1e39; fmt.Println(x);             // コンパイルエラー constant 1e+39 overflows float32
    x = 1e-45; fmt.Println(x);              // 1e-45
    x = 1e-46; fmt.Println(x);              // 0
}

定数の場合

package main

import "fmt"

func main() {
    fmt.Println(1.0 + 1e-15)          // 1.000000000000001
    fmt.Println(1.0 + 1e-16)          // 1
    fmt.Println((1.0 + 1e-130) - 1.0) // 9.016580681431383e-131
    fmt.Println((1.0 + 1e-131) - 1.0) // 0
    fmt.Println(1e308);               // 1e+308
    //fmt.Println(1e309);             // コンパイルエラー constant 1.00000e+309 overflows float64
    fmt.Println(1e-323);              // 1e-323
    fmt.Println(1e-324);              // 0
}

float32の場合のコードをfloat64にしたら、定数と同じ結果になった。

PHP

以下は私の PHP 5.3.10 の環境で実行した結果。

echo 1.0 + 1e-13;         // 1.0000000000001
echo 1.0 + 1e-14;         // 1
echo (1.0 + 1e-15) - 1.0; // 1.1102230246252E-15
echo (1.0 + 1e-16) - 1.0; // 0
echo 1e308;               // 1.0E+308
echo 1e309;               // INF
echo 1e-323;              // 9.8813129168249E-324
echo 1e-324;              // 0

2行目の 1.0 + 1e-141 と表示されるが、そこから 1.0 を引いても 0 にならないことから、内部では情報落ちせずに 1e-14 の情報も保持できていて、文字列に変換する際に丸められるだけのようである。

Python

以下は私の Python 2.7.3 の環境で実行した結果。

print 1.0 + 1e-11          # 1.00000000001
print 1.0 + 1e-12          # 1.0
print (1.0 + 1e-15) - 1.0  # 1.11022302463e-15
print (1.0 + 1e-16) - 1.0  # 0.0
print 1e308                # 1e+308
print 1e309                # inf
print 1e-323               # 9.88131291682e-324
print 1e-324               # 0.0

2行目の 1.0 + 1e-121 と表示されるが、そこから 1.0 を引いても 0 にならないことから、内部では情報落ちせずに 1e-12 の情報も保持できていて、文字列に変換する際に丸められるだけのようである。

以下は私の Python 3.3.2 の環境での実行結果。

print(1.0 + 1e-15)          # 1.000000000000001
print(1.0 + 1e-16)          # 1.0
print((1.0 + 1e-15) - 1.0)  # 1.1102230246251565e-15
print((1.0 + 1e-16) - 1.0)  # 0.0
print(1e308)                # 1e+308
print(1e309)                # inf
print(1e-323)               # 1e-323
print(1e-324)               # 0.0

Python2とPython3とで表示時の精度が違うみたい。

Ruby

以下は私のRuby 1.9.3p429 の環境で実行した結果。

p 1.0 + 1e-15         # 1.000000000000001
p 1.0 + 1e-16         # 1.0
p (1.0 + 1e-15) - 1.0 # 1.1102230246251565e-15
p (1.0 + 1e-16) - 1.0 # 0.0
p 1e308               # 1.0e+308
p 1e309               # Infinity
p 1e-323              # 1.0e-323
p 1e-324              # 0.0

Perl

以下は私のPerl 5.14.2 の環境で実行した結果。

print 1.0 + 1e-14;           # 1.00000000000001
print 1.0 + 1e-15;           # 1
print ((1.0 + 1e-15) - 1.0); # 1.11022302462516e-15
print ((1.0 + 1e-16) - 1.0); # 0
print 1e308;                 # 1e+308
print 1e309;                 # inf
print 1e-308;                # 9.99999999999999e-309
print 1e-309;                # 0
このサイトは筆者(hydrocul)の個人メモの集合です。すべてのページは永遠に未完成です。