NodeJS Websocket传输Float32Array时时间值不匹配问题求助
问题:Float32Array存储高精度时间值时出现精度丢失
你在Node.js中通过WebSocket传输二进制数据时,遇到了globalMsec存入Float32Array后值与原数据不符的问题——原时间值每3秒递增,但数组中存储的值偏大且仅每分钟左右变化,而其他随机浮点值却正常。
你的代码片段:
for( var i = 0; i < 100; i++ ) { var globalMsec = Date.now() / 1000.0 var outBuff = new Float32Array(6) outBuff[0] = 1.0 outBuff[1] = 123456789 outBuff[2] = globalMsec outBuff[3] = -5.0 //rapid wind dat outBuff[4] = Math.random() * 10 outBuff[5] = Math.random() * 360 console.log("globalMsec = "+globalMsec) console.log("[2] = "+outBuff[2]+" ==== ""[4] = "+outBuff[4]+" [5] " +"rnd2 = "+outBuff[5]) }
问题根源:Float32的精度限制
Float32Array使用单精度浮点数存储数据,它只有23位有效二进制位,对应十进制大约6-7位有效数字。而Date.now()/1000得到的时间值是一个形如1718XXXXXX.XXX的数字,整数部分已经有10位左右,远远超过了Float32的有效精度范围。
当你把这样的大数字存入Float32时,小数部分的精度会被截断,甚至整数部分的低位也会被舍入,导致存储后的值和原数值出现偏差。而且因为精度不足,只有当时间的整数部分(秒数)变化到能被Float32精确表示的程度时,数组中的值才会跟着变化,这就是为什么你看到它每分钟左右才变一次。
而outBuff[4]和outBuff[5]的数值范围小(0-10、0-360),有效数字远少于6位,所以能被Float32精确存储,每轮都能正常变化。
解决方法
有两种常见的修复方式:
改用Float64Array存储
双精度浮点数(Float64)有52位有效二进制位,对应十进制15-17位有效数字,完全足够保留Date.now()/1000的毫秒级精度:var outBuff = new Float64Array(6)拆分时间为整数秒+毫秒,用整数类型存储
如果需要严格控制二进制数据大小,可以把时间拆成两个部分,用整数数组存储:var seconds = Math.floor(globalMsec); var milliseconds = Math.round((globalMsec - seconds) * 1000); var outBuff = new Uint32Array(6); // 或者根据需求使用混合类型的ArrayBuffer outBuff[2] = seconds; outBuff[3] = milliseconds; // 可根据你的数据结构调整索引位置
内容的提问来源于stack exchange,提问作者Sam Grant
相关产品推荐
相关产品推荐

