うちのマシンは、int64じゃない!?
numpyのデータタイプ
これから、Numpyを使っていろいろと演算等を行うにあたって自分が何をやっているのか知っておく必要がある
つまり、π(パイ)はいくつなんだ?という話なのである。(実際は、いくつとしてデータに記録されるのかという話)
事の始まり
import numpy as np def ndarray_info(np_array): print("配列の軸数(次元) = ",np_array.ndim) print("各次元の配列のサイズ = ",np_array.shape) print("要素の総数 = ",np_array.size) print("要素の形式 = ",np_array.dtype) print("1要素のbyte数 = ",np_array.itemsize) print("-- a --") a = np.array([1,2,3]) ndarray_info(a) print("-- b --") b = np.array([1.2,2.3,3.4]) ndarray_info(b)
-- a --
配列の軸数(次元) = 1
各次元の配列のサイズ = (3,)
要素の総数 = 3
要素の形式 = int32
1要素のbyte数 = 4
-- b --
配列の軸数(次元) = 1
各次元の配列のサイズ = (3,)
要素の総数 = 3
要素の形式 = float64
1要素のbyte数 = 8
うぅ?
あれ、、、、、要素の形式 = int32 ってなんでint64じゃないの?
import sys print("Python version =",sys.version) print("Python platform =",sys.platform) print("Python intger=",sys.int_info) print("Python float =",sys.float_info)
Python version = 3.7.3 (default, Mar 27 2019, 17:13:21) [MSC v.1915 64 bit (AMD64)]
Python platform = win32
Python intger= sys.int_info(bits_per_digit=30, sizeof_digit=4)
Python float = sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308, min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15, mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)
Python自体は、タスクマネージャーを見る限り64bitプログラムとして動ている。プラットフォームがwin32
なのが気になるが。
intは、4byteで32bitなのね。floatは、8byteで64bitみたいだ。min_10_exp=-307, dig=15, mant_dig=53が、倍精度浮動小数点数とちょっと違うが表現の違いだけなのだろう。
で、Numpyはどうなのか?
import numpy as np print("np.float => ",np.finfo(np.float)) print("np.float_ => ",np.finfo(np.float_)) print("np.float32 => ",np.finfo(np.float32)) print("np.float64 => ",np.finfo(np.float64)) print("np.single => ",np.finfo(np.single)) print("np.double => ",np.finfo(np.double)) print("np.longdouble => ",np.finfo(np.longdouble)) print("float => ",np.finfo(float)) # floatは、OKみたいだ
np.float => Machine parameters for float64
---------------------------------------------------------------
precision = 15 resolution = 1.0000000000000001e-15
machep = -52 eps = 2.2204460492503131e-16
negep = -53 epsneg = 1.1102230246251565e-16
minexp = -1022 tiny = 2.2250738585072014e-308
maxexp = 1024 max = 1.7976931348623157e+308
nexp = 11 min = -max
---------------------------------------------------------------
np.float_ => Machine parameters for float64
---------------------------------------------------------------
precision = 15 resolution = 1.0000000000000001e-15
machep = -52 eps = 2.2204460492503131e-16
negep = -53 epsneg = 1.1102230246251565e-16
minexp = -1022 tiny = 2.2250738585072014e-308
maxexp = 1024 max = 1.7976931348623157e+308
nexp = 11 min = -max
---------------------------------------------------------------
np.float32 => Machine parameters for float32
---------------------------------------------------------------
precision = 6 resolution = 1.0000000e-06
machep = -23 eps = 1.1920929e-07
negep = -24 epsneg = 5.9604645e-08
minexp = -126 tiny = 1.1754944e-38
maxexp = 128 max = 3.4028235e+38
nexp = 8 min = -max
---------------------------------------------------------------
np.float64 => Machine parameters for float64
---------------------------------------------------------------
precision = 15 resolution = 1.0000000000000001e-15
machep = -52 eps = 2.2204460492503131e-16
negep = -53 epsneg = 1.1102230246251565e-16
minexp = -1022 tiny = 2.2250738585072014e-308
maxexp = 1024 max = 1.7976931348623157e+308
nexp = 11 min = -max
---------------------------------------------------------------
np.single => Machine parameters for float32
---------------------------------------------------------------
precision = 6 resolution = 1.0000000e-06
machep = -23 eps = 1.1920929e-07
negep = -24 epsneg = 5.9604645e-08
minexp = -126 tiny = 1.1754944e-38
maxexp = 128 max = 3.4028235e+38
nexp = 8 min = -max
---------------------------------------------------------------
np.double => Machine parameters for float64
---------------------------------------------------------------
precision = 15 resolution = 1.0000000000000001e-15
machep = -52 eps = 2.2204460492503131e-16
negep = -53 epsneg = 1.1102230246251565e-16
minexp = -1022 tiny = 2.2250738585072014e-308
maxexp = 1024 max = 1.7976931348623157e+308
nexp = 11 min = -max
---------------------------------------------------------------
np.longdouble => Machine parameters for float64
---------------------------------------------------------------
precision = 15 resolution = 1.0000000000000001e-15
machep = -52 eps = 2.2204460492503131e-16
negep = -53 epsneg = 1.1102230246251565e-16
minexp = -1022 tiny = 2.2250738585072014e-308
maxexp = 1024 max = 1.7976931348623157e+308
nexp = 11 min = -max
---------------------------------------------------------------
float => Machine parameters for float64
---------------------------------------------------------------
precision = 15 resolution = 1.0000000000000001e-15
machep = -52 eps = 2.2204460492503131e-16
negep = -53 epsneg = 1.1102230246251565e-16
minexp = -1022 tiny = 2.2250738585072014e-308
maxexp = 1024 max = 1.7976931348623157e+308
nexp = 11 min = -max
---------------------------------------------------------------
このプラットフォームが扱えるNumpyの浮動小数点は、float32(single)
とfloat64(double)
の2種類か
floatはfloat64と置き換えられるみたいだ
import numpy as np print("np.int => ",np.iinfo(np.int)) print("np.byte => ",np.iinfo(np.byte)) print("np.ubyte => ",np.iinfo(np.ubyte)) print("np.short => ",np.iinfo(np.short)) print("np.ushort => ",np.iinfo(np.ushort)) print("np.intc => ",np.iinfo(np.intc)) # C言語ライブラリのint print("np.uintc => ",np.iinfo(np.uintc)) # C言語ライブラリのuint print("np.int_ => ",np.iinfo(np.int_)) print("np.uint => ",np.iinfo(np.uint)) print("np.longlong => ",np.iinfo(np.longlong)) print("np.ulonglong => ",np.iinfo(np.ulonglong)) print("int => ",np.iinfo(int)) # intは、OKみたいだ
np.int => Machine parameters for int32
---------------------------------------------------------------
min = -2147483648
max = 2147483647
---------------------------------------------------------------
np.byte => Machine parameters for int8
---------------------------------------------------------------
min = -128
max = 127
---------------------------------------------------------------
np.ubyte => Machine parameters for uint8
---------------------------------------------------------------
min = 0
max = 255
---------------------------------------------------------------
np.short => Machine parameters for int16
---------------------------------------------------------------
min = -32768
max = 32767
---------------------------------------------------------------
np.ushort => Machine parameters for uint16
---------------------------------------------------------------
min = 0
max = 65535
---------------------------------------------------------------
np.intc => Machine parameters for int32
---------------------------------------------------------------
min = -2147483648
max = 2147483647
---------------------------------------------------------------
np.uintc => Machine parameters for uint32
---------------------------------------------------------------
min = 0
max = 4294967295
---------------------------------------------------------------
np.int_ => Machine parameters for int32
---------------------------------------------------------------
min = -2147483648
max = 2147483647
---------------------------------------------------------------
np.uint => Machine parameters for uint32
---------------------------------------------------------------
min = 0
max = 4294967295
---------------------------------------------------------------
np.longlong => Machine parameters for int64
---------------------------------------------------------------
min = -9223372036854775808
max = 9223372036854775807
---------------------------------------------------------------
np.ulonglong => Machine parameters for uint64
---------------------------------------------------------------
min = 0
max = 18446744073709551615
---------------------------------------------------------------
int => Machine parameters for int32
---------------------------------------------------------------
min = -2147483648
max = 2147483647
---------------------------------------------------------------
このプラットフォームが扱えるNumpyの整数は、8,16,32,64bit長の符号有り無しみたいだintはint32と置き換えられる
(この、マシン環境ではintはint64にならないMPUが古いから?)
まとめ
Numpyで使用されているデフォルトの形式を理解しておく必要がある。LinuxやWindowsまたはMPUの違いにより基礎となるC演算ライブラリ等が変わってくるからである。同じプログラムソースでもnp.array(raw)で作られる内部データ形式(dtype)がint32,int64やfloat32,float64と違う場合があるので演算結果に相違が出てくる場合がある。掛け算の掛け算とか総和を求める関数とかオーバーフローを起こしたり丸目誤差問題が発生したりなどである。最近のMPUであればint64,float64になっているので大きな数字を扱えるのでほとんど気にしないのかな?
(SSE関係は実装されているがAVX関係は実装されてないんだよなぁこのMPUだからなのかなぁ?普通にWindows 10なんだけど)
追記:stackoverflowに、同様の質問がありその結果は、Linux、MacOSは、int64になっているがWindowsはint32だということ。
int_ Default integer type (same as C long; normally either int64 or int32)
とのことで、windowsが定義しているC言語ライブラリがlongがint32でたのOSはlongはint64なのでそうなっているとのこと
うちのマシンが古すぎるせい!ってわけでなくよかったよ。
蛇足
import numpy as np pi_str = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679" pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 pi2 = 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 print("python π = ",pi_str,type(pi_str)) print("=== Python(Myマシン) ===") print("python π = ", pi,type(pi)) print("python 101桁pi2 = ",pi2,type(pi2)) pi3 = pi2 +1 print("python 101桁pi2 +1 = ",pi3,type(pi3)) piar = [pi] piar2 = [pi2] print("python array piar[0] = ", piar[0],type(piar[0])) print("python array piar2[0] = ", piar2[0],type(piar2[0])) print("=== Numpy float(Myマシン) ===") nppi = np.empty((1)) nppi[0] = pi print("np.array(π) = ",nppi,nppi.dtype) nppi_f64 = np.empty((1),dtype=np.float64) nppi_f64[0] = pi print("np.array(π,dtype=np.float64) = ", nppi_f64,nppi_f64.dtype) nppi_f32 = np.empty((1),dtype=np.float32) nppi_f32[0] = pi print("np.array(π,dtype=np.float32) = ", nppi_f32,nppi_f32.dtype) nppi_f16 = np.empty((1),dtype=np.float16) nppi_f16[0] = pi print("np.array(π,dtype=np.float16) = ", nppi_f16,nppi_f16.dtype) nppi_i = nppi.astype(np.int64) print("np.array(π).astype(np.int64) 整数化 = ",nppi_i,nppi_i.dtype) print("=== Numpy integer(Myマシン) ===") nppi2 = np.array(piar2) print("np.array(101桁整数) = ",nppi2,nppi2.dtype) nppi_i32 = np.array(piar2,dtype=np.int32) print("nppi_i32 = ",nppi_i32,nppi_i32.dtype)
python π = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 <class 'str'>
=== Python(Myマシン) ===
python π = 3.141592653589793 <class 'float'>
python 101桁pi2 = 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 <class 'int'>
python 101桁pi2 +1 = 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170680 <class 'int'>
python array piar[0] = 3.141592653589793 <class 'float'>
python array piar2[0] = 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 <class 'int'>
=== Numpy float(Myマシン) ===
np.array(π) = [3.14159265] float64
np.array(π,dtype=np.float64) = [3.14159265] float64
np.array(π,dtype=np.float32) = [3.1415927] float32
np.array(π,dtype=np.float16) = [3.14] float16
np.array(π).astype(np.int64) 整数化 = [3] int64
=== Numpy integer(Myマシン) ===
np.array(101桁整数) = [31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679] object
---------------------------------------------------------------------------
OverflowError Traceback (most recent call last)
<ipython-input-5-0da0a4edd8c4> in <module>
35 nppi2 = np.array(piar2)
36 print("np.array(101桁整数) = ",nppi2,nppi2.dtype)
---> 37 nppi_i32 = np.array(piar2,dtype=np.int32)
38 print("nppi_i32 = ",nppi_i32,nppi_i32.dtype)
OverflowError: Python int too large to convert to C long
import numpy as np import math def int_info(dt): dt_max = np.iinfo(dt).max a = math.log10(dt_max) print(dt,"max値 = ",dt_max,"(",int(a),"桁)") int_info(np.int) int_info(np.int8) int_info(np.int16) int_info(np.int32) int_info(np.int64) int_info(np.uint8) int_info(np.uint16) int_info(np.uint32) int_info(np.uint64)
<class 'int'> max値 = 2147483647 ( 9 桁)
<class 'numpy.int8'> max値 = 127 ( 2 桁)
<class 'numpy.int16'> max値 = 32767 ( 4 桁)
<class 'numpy.int32'> max値 = 2147483647 ( 9 桁)
<class 'numpy.int64'> max値 = 9223372036854775807 ( 18 桁)
<class 'numpy.uint8'> max値 = 255 ( 2 桁)
<class 'numpy.uint16'> max値 = 65535 ( 4 桁)
<class 'numpy.uint32'> max値 = 4294967295 ( 9 桁)
<class 'numpy.uint64'> max値 = 18446744073709551615 ( 19 桁)
パイソンに桁数は無いという話はあったが、整数の話であったか。小数点は、15桁まで表示している
対して、Numpyは、float64がpythonより少ない8桁何か変。float32は、7桁。float64
とfloat32
で1桁の差しかないのはおかしい。float16
とint
化はお約束ということで
Numpyの整数は、dtype=Noneの場合はなんかもう数値じゃなくオブジェクトとして扱っているし。int32はErrorなのね。有効桁数しらべたけどそんな感じなのね
と思ったが!調べていくと
import numpy as np pi_str = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679" pi = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 pi2 = 31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679 print("python π(文字列) = ",pi_str) print("=== Python(Myマシン) float ===") print("python π(有効桁) = ", pi) print("python π = ","%.100f" % pi) piar = [pi] print("python array(有効桁) = ", piar[0]) print("python array = ","%.100f" % piar[0]) print("=== Numpy float(Myマシン) ===") nppi = np.empty((1)) nppi[0] = pi nppi_f64 = np.empty((1),dtype=np.float64) nppi_f64[0] = pi nppi_f32 = np.empty((1),dtype=np.float32) nppi_f32[0] = pi nppi_f16 = np.empty((1),dtype=np.float16) nppi_f16[0] = pi print("str π = ",pi_str) print("flot π = ", nppi[0]) print("flot π(100桁表示) = ","%.100f" % nppi[0]) print("flot64 π = ", nppi_f64[0]) print("flot64 π(100桁表示) = ","%.100f" % nppi_f64[0]) print("flot32 π = ",nppi_f32[0]) print("flot32 π(100桁表示) = ","%.100f" % nppi_f32[0]) print("flot16 π = ",nppi_f16[0]) print("flot16 π(100桁表示) = ","%.100f" % nppi_f16[0])
python π(文字列) = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
=== Python(Myマシン) float ===
python π(有効桁) = 3.141592653589793
python π = 3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000
python array(有効桁) = 3.141592653589793
python array = 3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000
=== Numpy float(Myマシン) ===
str π = 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679
flot π = 3.141592653589793
flot π(100桁表示) = 3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000
flot64 π = 3.141592653589793
flot64 π(100桁表示) = 3.1415926535897931159979634685441851615905761718750000000000000000000000000000000000000000000000000000
flot32 π = 3.1415927
flot32 π(100桁表示) = 3.1415927410125732421875000000000000000000000000000000000000000000000000000000000000000000000000000000
flot16 π = 3.14
flot16 π(100桁表示) = 3.1406250000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
print表記の切り上げだったみたいです。pythonのデータ型とNumpyのデータ型ではprint表記の有効桁数が違うみたいでその影響みたいです
float64表現では、pythonとnumpyで同じ桁数のデータを保存していることがわかりました。