令人困惑的类型转换 - 2个字节到双倍

时间:2009-10-08 15:44:39

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

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

以下(java)片段是前一个编码器用于将字节数组转换为双精度数组的内容:

        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个字节)?任何人都可以用这段代码解释发生了什么吗?

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

5 个答案:

答案 0 :(得分:1)

从快速阅读中,我认为结果与以下相同:

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

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

它的范围比常规的双倍小得多,这可能是你的困惑。

假设无符号字节,有效值范围是从0到255.99609375的两倍,并且表示十进制值的范围有限。

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

答案 1 :(得分: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是一个非字节数组,那么代码才有意义,即使这样,它的转换也有点过于热心,因为&amp;无论如何,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 :(得分:0)

关键不是他除以256,而是256.0。使用整数操作数和double / float操作数的算术运算将产生double / float结果。如果两个操作数都是整数,那么结果将是一个整数。

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

Guard的回答:

(0xFF & byte) == byte

对于Java,情况并非如此,您可以将符号位提升为生成的int或float值。原始代码:

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

剥离符号位,同时:

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

显式保留它,使其包含在生成的float中。得到的转换值为-127到127加0到255/256。