浮動小数点とメモリイメージ(16進数文字列、HEX文字列、)の変換について →からの→ splitについて(再掲)
「見たまま編集」から「markdown記法」に更新しました...
いきさつ
>ほかにも javascriptで変換する物 とかあったのですが、
>また別途書くことにします。
ということで書いていきます。
#変換するだけならリンク先にどうぞ・・・
引用
今回調べたのは javascriptで変換する物 から引用した下記です。
var arrayClass = { 8: Float32Array, 16: Float64Array }; function calcDecimalFromBinary(value, nByte) { var buffer = new Uint8Array( (value + "0000000000000000").substr(0, nByte) .split(/(.{2})/) .map(function (b) { return parseInt(b, 16); } ).filter(isFinite).reverse()).buffer; return (new arrayClass[nByte](buffer))[0]; }
浮動小数点(数値)からメモリイメージ(16進数文字列、HEX文字列、)への変換に Float64Array を使っているだけなので、詳細はリンク先を確認ください。
本題
そしてやっと本題ですが、
読み下したときに意味不明だった「split(/(.{2})/)
」について調べてみました。
まず MDN の split の説明 を見る・・・
引用した「split(/(.{2})/)
」と同じような書き方はサンプルに登場せず、もやもやした感じが解決しません。
説明から動作を解明するのをあきらめて実際の動作を見ることにしました。
動作解析の準備
やりすぎた感じもありますが、処理中の結果をモニタ出来るように変更してみました。
function calcDecimalFromBinary(value, nByte) { var buf1 = (value + "0000000000000000"); var buf2 = buf1.substr(0, nByte); var buf3 = buf2.split(/(.{2})/); var sub_func = function (b) { return parseInt(b, 16); }; var buf4 = buf3.map(sub_func); var buf5 = buf4.filter(isFinite); var buf6 = buf5.reverse(); var buffer = new Uint8Array( buf6 ).buffer; return (new arrayClass[nByte](buffer))[0]; }
動作の説明
(1)「(value + "0000000000000000")
」と「.substr(0, nByte)
」で、入力されたHEX文字列を「nByte
」の長さにそろえています。
(2)問題の「.split(/(.{2})/)
」ですが・・・HEX文字列を分割している様子です。
(3)「function (b) { return parseInt(b, 16); };
」を「.map()
」の引数にセットして分割したHEX文字列を数値に変換しています。
(4)「.filter()
」は、配列の要素をテストしてテストに合格した要素を抽出します。 「isFinite
」は渡された値が有限数かどうかを判定します。 つまり、「.filter(isFinite)
」は配列の数値だけを抽出する記述となります。
・・・なぜ必要なのか不明でしたが「.split(/(.{2})/)
」の出力に関係がありました。
buf2 = '0102030405060708'
としたとき、
buf3 = [,'01',,'02',,'03',,'04',,'05',,'06',,'07',,'08',]
buf4 = [NaN,1,NaN,2,NaN,3,NaN,4,NaN,5,NaN,6,NaN,7,NaN,8,NaN]
buf5 = [1,2,3,4,5,6,7,8]
となり、NaNを取り除く必要があるためでした。
一応最後まで解説すると、
(5)「.reverse()
」で、配列の順番を逆転します。 結果は「buf6
」です。
(6)「buffer = new Uint8Array( buf6 ).buffer;
」で、型なし配列から型付き配列( 8 ビット符号なし整数値)を得ています。
(7)「return (new arrayClass[nByte](buffer))[0];
」で、型付き配列( 8 ビット符号なし整数値)から数値(浮動小数点)の配列を得て、その先頭要素を結果としてreturnしています。
※「arrayClass[nByte]
、nByte
=16」から「Float64Array
」が得られるので読み替えを実施してから考えるとよいです。
まとめ
文字列を文字数で分割する際に「文字列の分割」の語感に惑わされて?「.split(/(.{2})/)
」を使うと、
後で「.filter(isFinite)
」等の空き要素を省く処理が必要な場合があります。
これに対応する私のおすすめは「.match(/(.{2})/g)
」を使用することです。
引用した例の場合は「var buf3 = buf2.match(/(.{2})/g);
」の様に変更すると、
buf3 = ['01','02','03','04','05','06','07','08']
となるので、「.filter(isFinite)
」等の空き要素を省く処理が不要になります。
※文字数は、実際の処理に合わせて書き換えてください。
※MDN の match の説明 を参照してください。