2011-07-31 22 views
3

32ビットの符号なし "実数"の値が2つの16ビット符号付き "ワード"(0-65535)の値に分割されています。どうすればjavascript番号に変換できますか?32ビット符号なし "Real"データ型(2つの16ビット符号付きワードに分割)をjavascriptに変換

例: 値1:18584 値2:18081 実値は次のとおりです。20644.3

私は20644.3を返しback2Real(18584、18081)などの機能を探しています。値は、Modbusアプリケーション(NodeJS/modbus_stack)から取得されます。 SPS/modbusサーバは2つのワードレジスタに分割された "実"値を送信します。

よろしく、 root66

+0

私は数字がでているどのような形式「実」が何を意味するのかによって少し混乱していますか? IEEE浮動小数点? –

+0

これは32ビットのIEEE浮動小数点数です。最初の引数は下位16ビットで、2番目の引数は上位16ビットです。私はすぐに質問に答えるJavaScript関数を作る過程にあります。 –

答えて

2

は、JavaScriptの数値に変換するには、この機能を使用してください。 JavaScriptでは単精度数ではなく倍精度が使用されるため、丸めが発生することがあります。私はこれが役に立てば幸い

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] 
    } 
} 

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; 
} 

次の関数は、低域と高単語に分割、32ビットIEEE浮動小数点数にJavaScriptの数値を変換します。コードはパブリックドメインにあります。

+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 ] 
$