Pythonで作成した64ビットの浮動小数点数の数値を、そのままJavaScriptに持って行きたいことってありますよね?どっちもIEEE-754の64ビット(符号1ビット、仮数52ビット、指数11ビット)です。
そのまま渡せたらいいんですが、ダンプして10進数で出すと丸めとか行われてしまってうれしくありません。
このエントリーでは、誤差なしでそのまま浮動小数点数渡す方法を詳解します。
実際には、JavaScriptはECMAScriptの仕様で決められていて、PythonはCのdoubleと同じなので、結果としていまあるほとんどのOSの環境で同じフォーマットになっています。
Pythonで浮動小数点数バイト表現の文字列でエクスポートする
float64はstruct.packを使ってバイト配列にして、その後formatで16進数の文字列にします。ネットワークバイトオーダーで出しています。
dump.py
>>> import numpy as np
>>> import struct
>>> import binascii
>>> a = np.float64(10.12345456)
>>> binascii.hexlify(struct.pack("!d", a))
'40243f356fa37bf1'
今回の説明からは少しはずれますが、復元も次のようにして行えます。
load.py
>>> b = struct.unpack('!d', binascii.unhexlify('40243f356fa37bf1'))[0]
>>> a == b
True
JavaScriptでバイト表現の文字列をロードする
みなさんおなじみのTypedArrayを使います
> a = new ArrayBuffer(8)
> b = new Float64Array(a)
> c = new Uint32Array(a)
> d = '40243f356fa37bf1'
> c[0] = parseInt(d.slice(8, 16), 16)
> c[1] = parseInt(d.slice(0, 8), 16)
> b[0]
10.12345456
はい。読み込めました。Mac OS X 10.9上のPython 3.4とnode.js 0.12.2で試しました。