如何设置Java整数的第32位而不弄乱其打印的字符串表示形式

如何设置Java整数的第32位而不弄乱其打印的字符串表示形式,java,integer,unsigned,signed,Java,Integer,Unsigned,Signed,我正在尝试编写代码,以十六进制形式将CAN消息的数据字段的值打印为一系列短消息。CAN消息数据字段包含4个短消息,因此,例如,我可能会将一条消息打印为“FFFF EEEE ABAB 2013” 我可以用一个整数值对can消息的两个短消息进行编码,只要不设置整数的第32位,一切正常。因为Java使用有符号整数,所以设置第32位会导致它打印出一系列的“f”。我想要的是整数作为无符号值,这样打印出来就不会引起问题 下面是一个出错的例子: (int value): 0x80000000 (string

我正在尝试编写代码,以十六进制形式将CAN消息的数据字段的值打印为一系列短消息。CAN消息数据字段包含4个短消息,因此,例如,我可能会将一条消息打印为“FFFF EEEE ABAB 2013”

我可以用一个整数值对can消息的两个短消息进行编码,只要不设置整数的第32位,一切正常。因为Java使用有符号整数,所以设置第32位会导致它打印出一系列的“f”。我想要的是整数作为无符号值,这样打印出来就不会引起问题

下面是一个出错的例子:

(int value): 0x80000000
(string rep short 1): 0xffff8000
<crash>
我试图表示CAN消息数据的代码以及崩溃发生的代码:

public String getFormattedData() {
    String dataString = "";

    for(String aShort : Utility.splitStringByWhitespace(getData())) {
        try{
            dataString += ("0000".substring(0, 4 - aShort.length()) + aShort) + " ";
        } catch(Exception e) {
            System.out.println(getData());
            System.exit(1);
        }
    }

    return dataString.toUpperCase();
}
具体来说,发生崩溃的原因是“f”将short的字符串表示形式的长度增加到8个字符,因此“4-aShort.length()”将产生一个无效的负值

编辑:对于提问者,在这种特殊情况下,在将数据转换为字符串表示形式之前,我是如何使用整数对数据进行编码的:

public String convertToCANMessageData(PWMChannel channel) {
    int channelVal = channel.getValue();
    int entryDataHI = 0, entryDataLO = 0;

    entryDataHI += channelVal << 24;
    entryDataHI += smallData << 8;
    entryDataHI += (largeData >> 8) & 0xFF;
    entryDataLO += (largeData & 0xFF) << 24;

    if(ramping) {
        entryDataHI = entryDataHI | (1 << 16);
    } else {
        entryDataHI = entryDataHI & ~(1 << 16);
    }

    if(jumping) {
        entryDataHI = entryDataHI | (1 << 17);
    } else {
        entryDataHI = entryDataHI & ~(1 << 17);
    }

    if(frequencySetting) {
        entryDataHI = entryDataHI | (1 << 18);
    } else {
        entryDataHI = entryDataHI & ~(1 << 18);
    }

    return String.format("%x %x %x %x", entryDataHI >> 16, entryDataHI & 0xFFFF,
                            entryDataLO >> 16, entryDataLO & 0xFFFF);
}
public String convertToCANMessageData(PWMChannel通道){
int channelVal=channel.getValue();
int entryDataHI=0,entryDataLO=0;
entryDataHI+=channelVal 8)&0xFF;

entryDataLO+=(largeData&0xFF)我现在通过添加一个实用函数解决了这个问题:

public static int parseShort(String aShort) {
    if(aShort.length() > 4) aShort = aShort.substring(aShort.length()-4);

    return Integer.parseInt(aShort, 16);
}

如果有人有更好的解决方案,我很乐意将他们的答案标记为已接受,然后试一试。

只需使用无符号位移位即可获得整数的上半部分

int i = 0x80000000;
short s = (short)(i >>> 16);
s is 0x8000

要回答标题中的问题,要设置
int
的第32位,可以使用按位OR运算符:

myInteger |= (1 << 31);
更新:在格式化数字时使用无符号左移位
>>
:常规左移位
>
扩展符号位,以便负数的左移位保持负数,不会“突然”变成一个巨大的正数

return String.format("%x %x %x %x", entryDataHI >>> 16, entryDataHI & 0xFFFF,
                        entryDataLO >>> 16, entryDataLO & 0xFFFF);
或者,您可以使用您似乎已经熟悉的掩蔽:

return String.format("%x %x %x %x", (entryDataHI >> 16) & 0xFFFF, entryDataHI & 0xFFFF,
                        (entryDataLO >> 16) & 0xFFFF, entryDataLO & 0xFFFF);

在哪里可以在数字和字符串之间进行转换?我所看到的只是大量的字符串处理。使用long而不是int如何?它足够大,可以避免符号问题,只需要删除前导字符0s@Joni,我已经更新了详细信息。@Pablo,我也尝试了longs,但结果是我得到了类似0xFFFFFFFFD000的东西0xffffd000的。我现在看到了问题。请查看我的更新答案。它不会将它们视为无符号。FFFFFFFFF D是-3。FFFFFFFD base 16是4294967293 base 10。-3 base 10是-3 base 16。FFFFFFFFFD在base 10中是4294967293,如果将其视为无符号。如果将其视为有符号,则在base 16中的两个补码中的-3.-3是FFFFFFFFFD。否。在两个补码中的(更准确地说,是2-adic数字),-3是…FFD,无限长的1位字符串向左延伸。如果您仅限于使用有限数量的位,如32位数字,您可以将无限长的位字符串剪切到最右边的32位,以便将-3表示为FFFFFFF D,但在一般设置中,FFFFFFF D仍然是4294967293。+1,并且可以接受非常详细的设置ed回答。我以前不知道三箭头运算符,干杯。我想这就是算术和逻辑位移位之间的区别。这里的问题是,我将整数存储为字符串,然后尝试从中获取整数。0x8000000的字符串表示形式是“FFFFFF8000”,我得到一个NumberFormatException,试图将其解析回一个整数:在线程“AWT-EventQueue-0”java.lang中的异常。NumberFormatException:对于输入字符串:“ffffd000”除非你说我要做的是在将值转换为字符串之前将其保存为shorts,然后再将其转换回shorts,但这将涉及大量的重写。尽管如此,还是要感谢你。
return String.format("%x %x %x %x", entryDataHI >>> 16, entryDataHI & 0xFFFF,
                        entryDataLO >>> 16, entryDataLO & 0xFFFF);
return String.format("%x %x %x %x", (entryDataHI >> 16) & 0xFFFF, entryDataHI & 0xFFFF,
                        (entryDataLO >> 16) & 0xFFFF, entryDataLO & 0xFFFF);