浮動小数点数の精度
Go言語 (golang) 2015/03/01
以下は私の 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 2014/06/29
以下は私の 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-14
は 1
と表示されるが、そこから 1.0
を引いても 0
にならないことから、内部では情報落ちせずに 1e-14
の情報も保持できていて、文字列に変換する際に丸められるだけのようである。
Python 2014/07/02
以下は私の 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-12
は 1
と表示されるが、そこから 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 2014/06/29
以下は私の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 2013/09/21
以下は私の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