【问题标题】:Convert 32bit unsigned "Real" data type (splitted into two 16 bit signed words) to javascript将 32 位无符号“实数”数据类型(分成两个 16 位有符号字)转换为 javascript
【发布时间】:2011-10-16 18:02:03
【问题描述】:

我有一个 32 位无符号“实数”值拆分为两个 16 位有符号“字”(0-65535) 值。如何将它们转换为 javascript 数字?

示例: 值1:18584 值2:18081 真实值为:20644.3

我正在寻找像 back2Real(18584, 18081) 这样的函数,它返回 20644.3。这些值来自 modbus 应用程序(NodeJS / modbus_stack)。 SPS/modbus 服务器发送一个“Real”值,分成两个字寄存器。

问候, root66

【问题讨论】:

  • 我对“真实”的含义有点困惑,数字的格式是什么? IEEE 浮点数?
  • 这是一个 32 位 IEEE 浮点数,第一个参数是低 16 位,第二个参数是高 16 位。我正在制作一个 JavaScript 函数来尽快回答这个问题。

标签: javascript node.js floating-point


【解决方案1】:

缓冲区通常是数组。 稍微改变了第一个函数以接受数组,而不是低和高。 重要的是说它对没有交换的 Big Endian 格式有效。

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

    intView[0] = uint16array[0];
    intView[1] = uint16array[1];
    return floatView[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 ]
    $
    

    【讨论】:

    • 这个答案不考虑字节序。
    【解决方案3】:

    使用此函数转换为 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]   
      }
    }
    

    我希望这会有所帮助。代码在公共领域。

    【讨论】:

    • 什么是反向函数,把 32 位 IEEE 浮点数放进去,然后把低 16 位和高 16 位取出来?
    • 我已将该功能添加到我的答案中。
    猜你喜欢
    • 1970-01-01
    • 2019-05-30
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多