1

好的,我想将一组 THREE.Vector3 有效地保存到本地存储中。由于 javascript 使用字符串工作,我想使用最有效的比特率将 32 位浮点数转换为字符串。即理想的 32 位浮点 = 4 * 8 位,这在 C++ 之类的东西中很容易做到

问题似乎是第一个 Javascript 字符串是 UTF,其中包括一些填充

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

其次,我当前使用的代码 0 被转换为 '' 然后被省略,使得转换后的字节长度不可靠。

String.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 值的“面包​​和黄油”范围),您最终会得到无法打印的东西。因此,我们可以使用浮点数的 4 位值来使用长度为 8 的字符串,并将这些值偏移到可打印范围 (+32) 中,而不是使用浮点数的四个 ASCII 值创建长度为 4 的字符串。这是我的解决方案:

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 中也是如此)。因此,一个浮点数实际上需要 5.33 个字节(分数是可用的,即只要将数组编码为一个整体而不是单个浮点数,它就不是 6 个字节),但这仍然可以节省一些空间。

这是一个直接转换ArrayBuffer为base64字符串的函数(不是我的):https ://gist.github.com/958841

于 2012-10-17T12:09:09.900 回答