xxxxxxxxxx
78
function setup() {
createCanvas(400, 400);
// 16ビットのバッファ領域を確保
var buffer = new ArrayBuffer(2);
// 16ビットのデータを書き込み
var dv = new DataView(buffer);
// 144である「0x72 0x00」を書き込み(なお符号なしで書き込む)
dv.setUint16(0, 0b0001000000000001);
var littleEndian = false;
var result = readSFLOAT(dv, littleEndian);
console.log(result); // 114と表示される
}
function draw() {
background(220);
}
/**
* IEEE-11073 16-bit SFLOAT型をバイナリから取得し実数に変換する
*
* @param dv:DataView 16ビットのバイナリデータ
* @param littleEndian バイトオーダーの扱い(デフォルトは、fakse = ビッグエンディアン方式:)
*/
function readSFLOAT(dv, littleEndian = false) {
// 1. バイトオーダーを指定して16ビットデータを取得
var data = dv.getUint16(0, littleEndian);
// 2. 仮数部を取得する(16ビットの場合は下位12ビットが仮数部)
// - 取得した16ビットデータに下位12ビットの全てのフラグを立てた値を掛け算することで取得
var mantissa = data & 0x0fff;
// 仮数部も2の補数で判定するため16ビットのうちの12ビット中の上位1桁がマイナスを表していないかを確認
if ((mantissa & 0x0800) > 0) {
// もしマイナス値の場合は、1を引いた後反転処理と12ビット分の論理和を取得する)
mantissa = -1 * (~(mantissa - 0x01) & 0x0fff);
}
// 3. 指数部を取得する(16ビットの場合は上位4ビットが指数部)
// 上位4ビットを取得するためには16ビットの場合右へ12ビットシフトさせると取得可能
var exponential = data >> 12;
// 「仮数部 × 基数部 ^ 指数部」の公式に当てはめて変換
return mantissa * Math.pow(10, exponential);
}
/**
* IEEE-11073 32-bit FLOAT型をバイナリから取得し実数に変換する
*
* @param dv:DataView 32ビットのバイナリデータ
* @param littleEndian バイトオーダーの扱い(デフォルトは、fakse = ビッグエンディアン方式:)
*/
function readFLOAT(dv, littleEndian = false) {
// 1. バイトオーダーを指定して32ビットデータを取得
var data = dv.getUint32(0, littleEndian);
// 2. 仮数部を取得する(32ビットの場合は下位24ビットが仮数部)
// - 取得した32ビットデータに下位24ビットの全てのフラグを立てた値を掛け算することで取得
var mantissa = data & 0x00ffffff; // 下位24ビットのうちの上位1ビット目にフラグが立っていれば2の補数
// 仮数部が2の補数かどうかを判定する
if ((mantissa & 0x00800000) > 0) {
// 負の値の場合は、2の補数を用いて数値を求める
mantissa = -1 * (~(mantissa - 0x01) & 0x00ffffff);
}
// 3. 指数部を取得する(32ビットの場合は上位8ビットが指数部)
// 上位8ビットを取得するためには、32ビットの場合右へ24ビットシフトさせると取得可能
// なお、JavaScriptの場合「>>」を利用すると、符号を維持する右シフトであるため、
// ビット演算を用いると2の補数も考慮して10進数に変換してくれる
var exponential = data >> 24;
// 「仮数部 × 基数部 ^ 指数部」の公式に当てはめて変換
return mantissa * Math.pow(10, exponential);
}