2011-07-31 59 views
3

我有一個32位無符號「實數」值分成兩個16位有符號「字」(0-65535)值。我如何將它們轉換爲javascript數字?將32位無符號「真實」數據類型(分成兩個16位有符號字)轉換爲javascript

實施例: 值1:18584 值2:18081 的實際價值爲:20644.3

我在尋找像back2Real(18584,18081)的函數的返回20644.3。這些值來自modbus應用程序(NodeJS/modbus_stack)。 SPS/modbus服務器發送一個「真實」值分解爲兩個字寄存器。

問候, root66

+0

我對什麼是「真實」是什麼格式是數字的意思有點糊塗了? IEEE浮點? –

+0

這是一個32位IEEE浮點數,第一個參數是低16位,第二個參數是高16位。我正在編寫一個JavaScript函數來簡要回答這個問題。 –

回答

2

使用此功能轉換爲JavaScript數字。由於JavaScript使用雙精度而不是單精度數字,因此可能會發生一些舍入。

function back2Real(low, high){ 
    var fpnum=low|(high<<16) 
    var negative=(fpnum>>31)&1; 
    var exponent=(fpnum>>23)&0xFF 
    var mantissa=(fpnum&0x7FFFFF) 
    if(exponent==255){ 
    if(mantissa!=0)return Number.NaN; 
    return (negative) ? Number.NEGATIVE_INFINITY : 
     Number.POSITIVE_INFINITY; 
    } 
    if(exponent==0)exponent++; 
    else mantissa|=0x800000; 
    exponent-=127 
    var ret=(mantissa*1.0/0x800000)*Math.pow(2,exponent) 
    if(negative)ret=-ret; 
    return ret; 
} 

以下功能的JavaScript數字轉換爲32位IEEE浮點數,分成低和高字:

function real2Back(value){ 
    if(isNaN(value))return [0,0xFFC0] 
    if(value==Number.POSITIVE_INFINITY || value>=3.402824e38) 
    return [0,0x7F80] 
    if(value==Number.NEGATIVE_INFINITY || value<=-3.402824e38) 
    return [0,0xFF80] 
    var negative=(value<0) 
    var p,x,mantissa 
    value=Math.abs(value) 
    if(value==2.0)return [0,0x4000] 
    else if(value>2.0){ 
    // positive exponent 
    for(var i=128;i<255;i++){ 
    p=Math.pow(2,i+1-127) 
    if(value<p){ 
     x=Math.pow(2,i-127) 
     mantissa=Math.round((value*1.0/x)*8388608) 
     mantissa&=0x7FFFFF 
     value=mantissa|(i<<23) 
     if(negative)value|=(1<<31) 
     return [value&0xFFFF,(value>>16)&0xFFFF] 
    } 
    } 
    // return infinity 
    return negative ? [0,0xFF80] : [0,0x7F80] 
    } else { 
    for(var i=127;i>0;i--){ 
    // negative exponent 
    p=Math.pow(2,i-127) 
    if(value>p){ 
     x=p 
     mantissa=Math.round(value*8388608.0/x) 
     mantissa&=0x7FFFFF 
     value=mantissa|(i<<23) 
     if(negative)value|=(1<<31) 
     return [value&0xFFFF,(value>>16)&0xFFFF] 
    } 
    } 
    // subnormal 
    x=Math.pow(2,i-126) 
    mantissa=Math.round((value*8388608.0/x)) 
    if(mantissa>0x7FFFFF)mantissa=0x800000 
    value=mantissa 
    if(negative)value|=(1<<31) 
    return [value&0xFFFF,(value>>16)&0xFFFF] 
    } 
} 

我希望這有助於。該代碼在公共領域。

+0

它就像一個魅力!非常感謝你!! – root66

+0

什麼是反向函數,將32位IEEE浮點數加入並取出低位和高位16位? – root66

+0

我已將該功能添加到我的答案中。 –

2

您可以使用新(ish)類型的數組功能來簡化此操作。

function uint16ToFloat32(low, high) { 
    var buffer = new ArrayBuffer(4); 
    var intView = new Uint16Array(buffer); 
    var floatView = new Float32Array(buffer); 

    intView[0] = low; 
    intView[1] = high; 
    return floatView[0]; 
} 

function float32ToUint16(value) { 
    var buffer = new ArrayBuffer(4); 
    var intView = new Uint16Array(buffer); 
    var floatView = new Float32Array(buffer); 

    floatView[0] = value; 
    return [intView[0], intView[1]]; 
} 

console.log("Converted ints to", uint16ToFloat32(18584, 18081)); 
console.log("Converted float to", float32ToUint16(20644.297)); 

這裏的成績單:

$ node floatsplit.js 
Converted ints to 20644.296875 
Converted float to [ 18584, 18081 ] 
$ 
相關問題