1

OK、THREE.Vector3 の配列を効率的にローカル ストレージに保存したいと思います。javascript は文字列を使用して動作するため、最も効率的なビット比を使用して 32 ビットの浮動小数点数を文字列に変換したいと考えています。つまり、理想的には 32 ビット float = 4 * 8 ビットで、これは C++ などで簡単に実行できます。

問題は、最初のJavascript文字列がUTFであり、パディングが含まれているようです

http://en.wikipedia.org/wiki/UTF-8

次に、現在使用しているコード 0 が変換されてから省略されるため、変換されたバイト長が信頼できなくなります。

文字列.fromCharCode(0) == ''

var float2str = function(num)
{
    var bytestream = new Array();
    var view = new DataView(new ArrayBuffer(4));
    view.setFloat32(0,num);

    bytestream.push(view.getUint8(0));
    bytestream.push(view.getUint8(1));
    bytestream.push(view.getUint8(2));
    bytestream.push(view.getUint8(3));
    return String.fromCharCode(view.getUint8(0),view.getUint8(1),view.getUint8(2),view.getUint8(3))

}

var str2float = function(str)
{

    var bytestream = unpack(str)
    var view = new DataView(new ArrayBuffer(4));
    view.setUint8(0,bytestream[0]);
    view.setUint8(1,bytestream[1]);
    view.setUint8(2,bytestream[2]);
    view.setUint8(3,bytestream[3]);
    return view.getFloat32(0);
}

ありがとう!

4

2 に答える 2

1

秘訣は、符号なし 8 ビット整数の文字列値を印刷可能にすることです。8 ビットの数値が小さすぎたり大きすぎたりすると (ASCII 値の「パンとバター」の範囲外)、印刷できないものになってしまうことがわかりました。したがって、float からバイトの 4 つの ASCII 値を使用して長さ 4 の文字列を作成する代わりに、float からの 4 ビット値を使用して長さ 8 の文字列を使用し、それらの値を印刷可能な範囲 (+32) にオフセットすることができます。これが私の解決策です:

var offset = 33;

var float2str = function(num){
    var view = new DataView(new ArrayBuffer(4));
    view.setFloat32(0,num);

    var fourbits = [];
    for ( var i = 0; i < 4; i++ ){
        // split each byte into two 4-bit values
        fourbits.push(view.getUint8(0) >> 4);
        fourbits.push(view.getUint8(0) & 15);
    }

    for ( var i = 0; i < 8; i++ ){
        // build a string with offset four-bit values
        fourbits[i] = String.fromCharCode(offset+fourbits[i]);
    }
    return fourbits.join('');

};

var str2float = function(str){
    var bytestream = str;
    var view = new DataView(new ArrayBuffer(4));

    for(var i = 0; i < 4; i++){
        // re-convert the characters into bytes.
        view.setUint8(i, ((bytestream[i*2].charCodeAt() - offset) << 4) + bytestream[i*2+1].charCodeAt() - offset);
    }

    return view.getFloat32(0);
};

console.log(float2str('2.251')); // "%!\"!\"!'#"
console.log(str2float(float2str('2.251'))); // 2.250999927520752

これが役立つことを願っています。

于 2012-10-16T16:24:18.050 に答える
0

base64 エンコーディングを使用します。一度に 6 ビットを印刷可能な ASCII 文字に変換します (これは UTF-8 でも同じです)。そのため、実際には 1 つの浮動小数点数に対して 5.33 バイトが必要になります (小数部は使用可能です。つまり、配列を個別の浮動小数点数としてではなく全体としてエンコードする限り、6 バイトではありません)。

ArrayBufferbase64 文字列に直接変換する関数 (私のものではありません) は次のとおりです: https://gist.github.com/958841

于 2012-10-17T12:09:09.900 に答える