java中负数的 & >> >>> 运算案例

public class Test {
    public static void main(String[] args) {
        //  java中负数的 & >> >>> 运算 案例

        // 1.byte的范围问题
        // b = 0b01000000
        byte b = 64;
        // b = b + 64; // 编译报错,byte在运算时会先转成int类型再运算,结果也是int类型,int -> byte 需要强转
        b += b; // += 会把结果自动进行强转
        // b 转为int : 0b01000000 --> 0b00000000 00000000 00000000 01000000
        // 输出-128,b + b = 0b00000000 00000000 00000000 01000000 + 0b00000000 00000000 00000000 01000000 = 0b00000000 00000000 00000000 10000000
        // 结果0b00000000 00000000 00000000 10000000 转为byte-> 0b10000000 = -128的补码 = -128
        formatPrint("b + b = %s + %s = 0b%s = %s", toBinaryString(64), toBinaryString(64), Integer.toBinaryString(b).substring(24), b);
        b = 64 + 63;    // jvm对常量运算做了优化,直接把运算的结果赋值给b
        // b = 64 + 64;  // 编译报错,因为64+64超出byte的范围,不能用byte接收
        formatPrint("64 + 63 = %s + %s = %s = %s", toBinaryString(64), toBinaryString(63), toBinaryString(b), b);
        formatPrint("-----------------------------------------------------------------------");

        // 2.负数运算操作 & >> >>>
        // 计算机的运算都是用补码来计算的,正数:原码=反码=补码,负数:反码=除符号位原码各位取反,补码=反码+1
        b = -1;   // -1:0b10000001(原) -> 0b11111110(反) -> 0b11111111(补)
        // b转为int类型:0b10000000 00000000 00000000 00000001(原) -> 0b11111111 11111111 11111111 11111110(反) -> 0b11111111 11111111 11111111 11111111(补)
        // i = 0b11111111 11111111 11111111 11111111 & 0b00000000 00000000 00000000 11111111 = 0b00000000 00000000 00000000 11111111 = 255
        int i = b & 0xFF;
        formatPrint("-1 & 0xFF = %s & %s = %s = %s", toBinaryString(b), toBinaryString(0xFF), toBinaryString(i), i);
        // >> :带符号右移,正数右移高位补0,负数右移高位补1
        int i2 = b >> 4;    // i2 = 0b11111111 11111111 11111111 11111111 >> 4 = 0b11111111 11111111 11111111 11111111 = -1补码 = -1
        formatPrint("-1 >> 4 = %s >> %s = %s = %s", toBinaryString(b), 4, toBinaryString(i2), i2);
        // >>> :无符号右移,无论是正数还是负数,高位都补0
        int i3 = b >>> 4;   // i3 = 0b11111111 11111111 11111111 11111111 >>> 4 = 0b00001111 11111111 11111111 11111111 = 268435455
        formatPrint("-1 >>> 4 = %s >>> %s = %s = %s", toBinaryString(b), 4, toBinaryString(i3), i3);

        formatPrint("-----------------------------------------------------------------------");
        // 再如 -127
        b = -127;   // -1:0b11111111(原) -> 0b10000000(反) -> 0b10000001(补)
        // b转为int类型:0b10000000 00000000 00000000 01111111(原) -> 0b11111111 11111111 11111111 10000000(反) -> 0b11111111 11111111 11111111 10000001(补)
        i = b & 0xFF;   // i = 0b11111111 11111111 11111111 10000001 & 0b00000000 00000000 00000000 11111111 = 0b00000000 00000000 00000000 10000001 = 129
        formatPrint("%s & 0xFF = %s & %s = %s = %s", b, toBinaryString(b), toBinaryString(0xFF), toBinaryString(i), i);
        i2 = b >> 4;
        formatPrint("%s >> 4 = %s >> %s = %s = %s", b, toBinaryString(b), 4, toBinaryString(i2), i2);
        i3 = b >>> 4;
        formatPrint("%s >>> 4 = %s >>> %s = %s = %s", b, toBinaryString(b), 4, toBinaryString(i3), i3);
    }

    /**
     * 格式化输出字符串
     * @param format 要格式化的字符串
     * @param args 参数
     */
    private static void formatPrint(String format, Object ... args) {
        System.out.println(String.format(format, args));
    }

    /** int类型十进制转二进制 保持32位,i为负值时,返回的是其二进制的补码 */
    private static String toBinaryString(int i) {
        String bs = Integer.toBinaryString(i);
        String pre = IntStream.range(0, 32 - bs.length()).mapToObj(x -> "0").collect(Collectors.joining());
        return String.format("0b%s%s", pre, bs);
    }

    /** int类型十进制转十六进制 保持8位,i为负值时,返回的是其十六进制的补码 */
    private static String toHexString(int i) {
        return String.format("%#010x", i);
    }
}

案例:将byte数组转十六进制字符串


public class TestExample {

    public static void main(String[] args) throws Exception {
    	// sha256加密一个数 返回的是一个byte数组
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] encrypted = md.digest("3".getBytes(StandardCharsets.UTF_8));
        // 將 byte 转换16进制 string
        String result;
        // 1 遍历逐个转换
        StringBuilder strHexString = new StringBuilder();
        // 遍历byte buffer
        for (byte b : encrypted) {
//            String hex = Integer.toHexString(0xff & b).toUpperCase();
//            if (hex.length() == 1) {
//                strHexString.append('0');
//            }
//            strHexString.append(hex);
            // 保持两位不足用0补全
            strHexString.append(String.format("%02X", b));
        }
        result = strHexString.toString();
        System.out.println(result.length());
        System.out.println(result);
        // 2 先转换为BigInteger类型,再使用toString方法转换
        result = new BigInteger(encrypted).toString(16).toUpperCase();
        System.out.println(result);
        // 3 调用DatatypeConverter.printHexBinary方法
        result = DatatypeConverter.printHexBinary(encrypted);
        System.out.println(result);
        result = printHexBinary(encrypted);
        System.out.println(result);
    }

    // 同 DatatypeConverter.printHexBinary
    private static String printHexBinary(byte[] data) {
        char[] hexCode = "0123456789ABCDEF".toCharArray();
        StringBuilder r = new StringBuilder(data.length * 2);
        for (byte b1 : data) {
            int b = b1 & 0xFF;  // 将byte的负值转为int类型的正值
            // byte 共八位二进制 相当于两位十六进制
            r.append(hexCode[b >>> 4]); // 取前四位的值
            r.append(hexCode[(b & 0xF)]);   // 取后四位的值
        }
        return r.toString();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值