win10 home上の jupyter notebook で*1何故か計算が合わないので、printdebug していたら、numpy.power がどうも合わない*2。
import math import numpy as np for i in range(1,16): print(f"{i:>2} {pow(10,i):>20} {math.pow(10,i):>20} {np.power(10,i):>20}")
で
1 10 10.0 10 2 100 100.0 100 3 1000 1000.0 1000 4 10000 10000.0 10000 5 100000 100000.0 100000 6 1000000 1000000.0 1000000 7 10000000 10000000.0 10000000 8 100000000 100000000.0 100000000 9 1000000000 1000000000.0 1000000000 10 10000000000 10000000000.0 1410065408 11 100000000000 100000000000.0 1215752192 12 1000000000000 1000000000000.0 -727379968 13 10000000000000 10000000000000.0 1316134912 14 100000000000000 100000000000000.0 276447232 15 1000000000000000 1000000000000000.0 -1530494976
なので、どうも numpy のようです。
ちなみに
np.__version__ '1.21.2' import sys sys.version '3.7.11 (default, Jul 27 2021, 09:42:29) [MSC v.1916 64 bit (AMD64)]'
ついでに、
for i in range(33): print(f"{i:>2} {pow(2,i):>15} {np.power(2,i):>15}")
で
0 1 1 1 2 2 2 4 4 3 8 8 4 16 16 5 32 32 6 64 64 7 128 128 8 256 256 9 512 512 10 1024 1024 11 2048 2048 12 4096 4096 13 8192 8192 14 16384 16384 15 32768 32768 16 65536 65536 17 131072 131072 18 262144 262144 19 524288 524288 20 1048576 1048576 21 2097152 2097152 22 4194304 4194304 23 8388608 8388608 24 16777216 16777216 25 33554432 33554432 26 67108864 67108864 27 134217728 134217728 28 268435456 268435456 29 536870912 536870912 30 1073741824 1073741824 31 2147483648 -2147483648 32 4294967296 0
になりますです。
少しいじって、引数のどちらかをfloat にして
for i in range(34): print(f"{i:>4} {np.power(10.0,i):>25} {np.power(10,float(i)):>25} {np.power(10,1.0*i):>25} {np.power(10,i):>25}")
計算すると、
0 1.0 1.0 1.0 1 1 10.0 10.0 10.0 10 2 100.0 100.0 100.0 100 3 1000.0 1000.0 1000.0 1000 4 10000.0 10000.0 10000.0 10000 5 100000.0 100000.0 100000.0 100000 6 1000000.0 1000000.0 1000000.0 1000000 7 10000000.0 10000000.0 10000000.0 10000000 8 100000000.0 100000000.0 100000000.0 100000000 9 1000000000.0 1000000000.0 1000000000.0 1000000000 10 10000000000.0 10000000000.0 10000000000.0 1410065408 11 100000000000.0 100000000000.0 100000000000.0 1215752192 12 1000000000000.0 1000000000000.0 1000000000000.0 -727379968 13 10000000000000.0 10000000000000.0 10000000000000.0 1316134912 14 100000000000000.0 100000000000000.0 100000000000000.0 276447232 15 1000000000000000.0 1000000000000000.0 1000000000000000.0 -1530494976 16 1e+16 1e+16 1e+16 1874919424 17 1e+17 1e+17 1e+17 1569325056 18 1e+18 1e+18 1e+18 -1486618624 19 1e+19 1e+19 1e+19 -1981284352 20 1e+20 1e+20 1e+20 1661992960 21 1e+21 1e+21 1e+21 -559939584 22 1e+22 1e+22 1e+22 -1304428544 23 1.0000000000000001e+23 1.0000000000000001e+23 1.0000000000000001e+23 -159383552 24 1e+24 1e+24 1e+24 -1593835520 25 1e+25 1e+25 1e+25 1241513984 26 1e+26 1e+26 1e+26 -469762048 27 1e+27 1e+27 1e+27 -402653184 28 1e+28 1e+28 1e+28 268435456 29 1e+29 1e+29 1e+29 -1610612736 30 1e+30 1e+30 1e+30 1073741824 31 1e+31 1e+31 1e+31 -2147483648 32 1e+32 1e+32 1e+32 0 33 1e+33 1e+33 1e+33 0
と合うようになりました。
ついでに、
for i in range(33): print(f"{i:>4} {np.power(2.0,i):>20} {np.power(2,float(i)):>20} {np.power(2,i*1.0):>20} {np.power(2,i):>20}")
も、
0 1.0 1.0 1.0 1 1 2.0 2.0 2.0 2 2 4.0 4.0 4.0 4 3 8.0 8.0 8.0 8 4 16.0 16.0 16.0 16 5 32.0 32.0 32.0 32 6 64.0 64.0 64.0 64 7 128.0 128.0 128.0 128 8 256.0 256.0 256.0 256 9 512.0 512.0 512.0 512 10 1024.0 1024.0 1024.0 1024 11 2048.0 2048.0 2048.0 2048 12 4096.0 4096.0 4096.0 4096 13 8192.0 8192.0 8192.0 8192 14 16384.0 16384.0 16384.0 16384 15 32768.0 32768.0 32768.0 32768 16 65536.0 65536.0 65536.0 65536 17 131072.0 131072.0 131072.0 131072 18 262144.0 262144.0 262144.0 262144 19 524288.0 524288.0 524288.0 524288 20 1048576.0 1048576.0 1048576.0 1048576 21 2097152.0 2097152.0 2097152.0 2097152 22 4194304.0 4194304.0 4194304.0 4194304 23 8388608.0 8388608.0 8388608.0 8388608 24 16777216.0 16777216.0 16777216.0 16777216 25 33554432.0 33554432.0 33554432.0 33554432 26 67108864.0 67108864.0 67108864.0 67108864 27 134217728.0 134217728.0 134217728.0 134217728 28 268435456.0 268435456.0 268435456.0 268435456 29 536870912.0 536870912.0 536870912.0 536870912 30 1073741824.0 1073741824.0 1073741824.0 1073741824 31 2147483648.0 2147483648.0 2147483648.0 -2147483648 32 4294967296.0 4294967296.0 4294967296.0 0
答えが合う模様です。numpy.arangeでも step を1.0にしないと range と同じでした。
wsl上の python3 でも試してみたのですが、合わない計算結果同士は合わないけれども wsl上でも numpy の模様。対処法も一緒。
import numpy as np for i in range(25): print(f"{i:>2} {np.power(10.0,i):>30} {np.power(10,i):>30}") import sys print(sys.version) print(np.__version__)
0 1.0 1 1 10.0 10 2 100.0 100 3 1000.0 1000 4 10000.0 10000 5 100000.0 100000 6 1000000.0 1000000 7 10000000.0 10000000 8 100000000.0 100000000 9 1000000000.0 1000000000 10 10000000000.0 10000000000 11 100000000000.0 100000000000 12 1000000000000.0 1000000000000 13 10000000000000.0 10000000000000 14 100000000000000.0 100000000000000 15 1000000000000000.0 1000000000000000 16 1e+16 10000000000000000 17 1e+17 100000000000000000 18 1e+18 1000000000000000000 19 1e+19 -8446744073709551616 20 1e+20 7766279631452241920 21 1e+21 3875820019684212736 22 1e+22 1864712049423024128 23 1e+23 200376420520689664 24 1e+24 2003764205206896640 3.6.9 (default, Jan 26 2021, 15:33:00) [GCC 8.4.0] 1.13.3
wsl 上で2の n 乗の合わないさわりの部分だけ計算すると、
for i in range(66): if np.power(2,i)!=pow(2,i): print(i,np.power(2,i))
で
63 -9223372036854775808 64 0 65 0
こんな感じ。
wsl からもどって windows prompt 上でも jupyternotebook 上でも
import numpy as np print(np.power(2,30)*2)
を実行すると、
RuntimeWarning: overflow encountered in int_scalars print(np.power(2,30)*2) -2147483648
となるので、まぁそういうことらしい。
問題のあるところは僕にはわからないけれど、遊んでみるには非常に面白かった。
とりあえず、きちんと動かす方法はわかっているので一段落?