【问题标题】:Confusing type conversion - 2 Bytes to Double令人困惑的类型转换 - 2 字节到双倍
【发布时间】:2010-12-05 01:10:36
【问题描述】:

我最近被要求接管一个项目,在该项目中,波形数据从电源转换器中采样并发送到智能代理,在该代理中进行计算并根据结果采取适当的行动。

下面的(java)sn-p是前面编码器用来将字节数组转换成双精度数组的:

        LSB = (0XFF & (int)ipPacket[index]);
        double temp = LSB/256.0;

        MSB = (byte)(0XFF & (byte)ipPacket[index+1]);
        double output = (double)(MSB + temp);

        ConvCurrentPhaseR[doubleArrayIndex] = (double)(output);

(注:LSB为整数,MSB为字节)

老实说,我不知道以前的编码员是如何提出这种转换的。这对我来说没有任何意义。为什么要将 LSB 除以 256?即使原始数据是浮点数(4 字节),我们如何从仅 2 字节中得到双精度(8 字节)?谁能解释这段代码发生了什么?

提前感谢您提供的任何帮助!

【问题讨论】:

    标签: java floating-point double byte type-conversion


    【解决方案1】:

    这是我的猜测......在某些情况下,重申或巩固其他人所说的,但在上下文中。

    源数据为 16 位定点格式。这比 float 或 double 具有更小的范围,但比 16 位浮点具有更高的精度。这里,8位有符号位分配给整数部分,8位分配给小数部分。

    对于不熟悉定点表示的人来说,这类似于将货币值保持为整数“美分”,同时除以 100 以显示“美元”。

        LSB = (0XFF & (int)ipPacket[index]);
        double temp = LSB/256.0;
    

    在上面,第一个字节使用浮点除法转换为值的小数部分。 LSB/256.0 将产生一个介于 0.0 和 0.99609375 之间的双精度值。

        MSB = (byte)(0XFF & (byte)ipPacket[index+1]);
    

    上面的代码应该是规范化第二个字节。如果 ipPacket 是一个 byte[] 数组,那么这没有做任何事情,因为符号位已经很好了。 ipPacket[index+1] 应该已经在 -128 和 127 之间。代码只有在 ipPacket 是一个非字节数组时才有意义,即使这样,它的转换也有点过分热心,因为 & 0XFF 会将值提升为无论如何都是一个整数......在将其转换回字节之前。

    鉴于原始代码最后一行中不必要的(双重)强制转换,我怀疑上面的一些可能也不需要。

    如果 ipPacket 是一个 byte[] 数组,那么:

    MSB = ipPacket[index+1];
    

    应该没问题。如果 ipPacket 不是 byte[] 数组,那么以下内容应该仍然足够:

    MSB = (byte)(0xFF & ipPacket[index+1]);
    

    正如其他人所说,最后一位结合了整数和小数部分:

        double output = (double)(MSB + temp);
        ConvCurrentPhaseR[doubleArrayIndex] = (double)(output);
    

    虽然重要的是要注意小数部分添加到整数部分。这意味着 MSB = -1 和 LSB = 128 将导致 -0.5 而不是人们最初预期的 -1.5。

    【讨论】:

      【解决方案2】:

      注意Guard的回答:

      (0xFF & byte) == byte
      

      这不适用于 Java,您可以将符号位提升为结果 int 或 float 值。原代码:

      (0XFF & (int)ipPacket[index]);
      

      去掉符号位,而:

      (byte)(0XFF & (byte)ipPacket[index+1]);
      

      明确保留它,以便它包含在生成的浮点数中。转换的结果值为 -127 到 127 加上 0 到 255/256。

      【讨论】:

        【解决方案3】:

        通过快速阅读,在我看来结果与以下内容相同:

        output = (double)(ipPacket[index + 1] + (ipPacket[index] / 256.0));
        

        这是假设 ipPacket 是一个字节数组,并且 (0xFF & byte) == byte。他有效地将双精度的小数部分存储在ipPacket[index] 中作为1/256 的倍数,并将整数部分存储在ipPacket[index+1] 中。

        它的范围比普通的 double 小得多,这可能是您感到困惑的地方。

        值的有效范围(假设为无符号字节)是从 0 到 255.99609375 的双精度值,表示十进制值的范围有限。

        编辑: 值 256 不包括在内,因为无符号字节的范围为 0-255,小数区域的范围为 0 - (255/256 == .99609375)

        【讨论】:

          【解决方案4】:

          我的猜测是第一个字节包含小数点后的部分为“x/256”,第二个字节包含小数点前的部分。

          因此,对于 4.5,第一个字节为 128(128/256 = 1/2 = 0.5),第二个字节为 4,结果是两者相加。

          【讨论】:

            【解决方案5】:

            关键不是他除以 256,而是除以256.0。具有整数操作数和双精度/浮点操作数的算术运算将产生双精度/浮点结果。如果两个操作数都是整数,那么结果就是整数。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2012-09-12
              • 2020-10-18
              • 1970-01-01
              • 1970-01-01
              • 2011-02-02
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多