[Java SE] 经典问题:超出Java Long型(8字节/64位)的二进制比特流数据如何进行大数的数值计算?
0 问题描述
- 经典问题:超出Java Long型(8字节/64位)的二进制比特流数据如何进行大数的数值计算?
 
近期工作上遇到了这个问题:需要将一个无符号数、且位长
>=8字节(等于8字节时,首位bit为1,其他bit不全为0)的二进制字符串转为Java****对象(原始整数),进行整型运算、或浮点数运算浮点运算的思路:result = 原始整数 * 精度 + 偏移量
- 解决思路:将二进制字符串转为byte数组,再转为BigInteger大整型数。如果基于进行浮点运算时,可将 BigInteger 大整型数对象再转为 BigDecimal。
 
new BigDecimal v = new BigDecimal(new BigInteger(xxx))
1 解决过程示例
- 二进制数据:"1100000001000000110010110000000000000000000000000000000000000000" (需考虑————情况1:作为有符号数;情况2:作为无符号数)
 
16进制:
0xc040cb0000000000L
11000000
01000000
11001011
00000000
00000000
00000000
00000000
00000000
1.1 测试用例1:无符号数、且位长>=8字节(等于8字节时,首位bit为1,其他bit不全为0)的情况
    /** 针对 长度为 64 bit、无符号数 的CAN信号,且第1位为1的情况 :使用 BigInteger
     * @description Java中没有内置的无符号8字节整数类型,但是可以使用 `java.math.BigInteger` 类来处理任意大的整数值,包括无符号整数
     * @refernce-doc
     **/
    public static void unsigned8BytesDataTest(){
        // 一个8字节的无符号整数
        long longValue =  0xc040cb0000000000L; //0x10000000000000000L;
        String longStr = "c040cb0000000000";//canFrameContent
        // 转为二进制字符串
        String binStr = BytesUtil.hexStringToBinaryString(longStr);
        System.out.println("binStr: " + binStr);//1100000001000000110010110000000000000000000000000000000000000000
        // 将无符号长整数转换为 BigInteger | 方式1: BigInteger
        BigInteger value = toUnsignedBigInteger(longValue);
        System.out.println("value : " + value);//1385 3295 6546 5208 4224
        //二进制字符串转Java数据对象 | 测验 Long.parseLong(binStr , 2) | 若没有报错,则说明OK
        BigInteger value2 = toUnsignedBigInteger(binStr);
        System.out.println("value2 : " + value2);//1385 3295 6546 5208 4224
        //二进制字符串转Java数据对象 | 测验 Long.parseLong(binStr , 2) | 若没有报错,则说明OK
        Long value3 = Long.parseLong(binStr, 2);
        System.out.println("value3 : " + value3);//报错信息如下
//        Exception in thread "main" java.lang.NumberFormatException: For input string: "1100000001000000110010110000000000000000000000000000000000000000"
//        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
//        at java.lang.Long.parseLong(Long.java:592)
//        at ParseTest.unsigned8BytesDataTest(ParseTest.java:213)
//        at ParseTest.main(ParseTest.java:29)
        }
1.2 测试用例2:有符号数、且位长>=8字节(等于8字节时,首位bit为1,其他bit不全为0)的情况
    /**
     * 有符号数、8字节
     * 最终目标: 二进制字符串 转 Java 数据对象
     */
    public static void signed8BytesDataTest(){
        // 一个8字节的无符号整数
        long longValue =  0xc040cb0000000000L; //0x10000000000000000L;
        String longStr = "c040cb0000000000";//canFrameContent
        // 转为二进制字符串
        String binStr = BytesUtil.hexStringToBinaryString(longStr);
        System.out.println("binStr: " + binStr);//1100000001000000110010110000000000000000000000000000000000000000
        // 将有符号长整数转换为 BigInteger | 方式1: BigInteger
        BigInteger value = toUnsignedBigInteger(longValue);
        System.out.println("value : " + value);//-459 3448 4190 5746 7392
        //二进制字符串转Java数据对象 | 测验 Long.parseLong(binStr , 2) | 若没有报错,则说明OK
        BigInteger value2 = toUnsignedBigInteger(binStr);
        System.out.println("value2 : " + value2);//1385 3295 6546 5208 4224
        //二进制字符串转Java数据对象 | 测验 Long.parseLong(binStr , 2) | 若没有报错,则说明OK
        Long value3 = Long.parseLong(binStr, 2);
        System.out.println("value3 : " + value3);//报错信息如下
//        Exception in thread "main" java.lang.NumberFormatException: For input string: "1100000001000000110010110000000000000000000000000000000000000000"
//        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
//        at java.lang.Long.parseLong(Long.java:592)
//        at ParseTest.signed8BytesDataTest(ParseTest.java:241)
//        at ParseTest.main(ParseTest.java:30)
    }
1.X 工具方法:toUnsignedBigInteger(long unsignedLong/String binStr)
    private static BigInteger toUnsignedBigInteger(long unsignedLong) {
        // 将无符号的8字节长整数转换为字节数组
        byte[] bytes = ByteBuffer.allocate(8).putLong(unsignedLong).array();
        // 使用字节数组创建BigInteger
        return new BigInteger(1, bytes);
    }
    /** 二进制字符串 **/
    private static BigInteger toUnsignedBigInteger(String binStr) {
        byte[] bytes = null;
        try {
            // 将无符号的8字节长整数转换为字节数组
            bytes = BytesUtil.binaryStringToBinaryArray(binStr);
        } catch (Exception exception) {
            log.error("Fail to convert as big integer!binStr : {}, exception : {}", binStr, exception);
        }
        // 使用字节数组创建BigInteger
        return new BigInteger(1, bytes);
    }
X 参考文献
[Java SE] 经典问题:超出Java Long型(8字节/64位)的二进制比特流数据如何进行大数的数值计算?的更多相关文章
- 【Java SE】如何用Java实现直接选择排序
		
摘要:直接选择排序属于选择排序的一种,但是它的排序算法比冒泡排序的速度要快一些,由于它的算法比较简单,所以也比较适合初学者学习掌握. 适宜人群:有一定Java SE基础,明白Java的数据类型,数组的 ...
 - 【Java SE】如何用Java实现插入排序
		
摘要:前面三期分别写了三篇简单排序的算法,今天来讲一点稍微难一点的排序算法-----插入排序. 基本思想: 设n个数据已经按照顺序排列好(假定从小排到大). 输入一个数据x,将其放在恰当的位置,使其顺 ...
 - 【Java SE】如何用Java实现反转排序
		
摘要:反转排序是将原先已经排序好了的重新排序,是原来的数组元素的顺序反转过来.假设原来的数组顺序是{6,5,4,3,2,1},反转之后的顺序就是{1,2,3,4,5,6}.这个排序的算法不是很难,代码 ...
 - Java SE 6 新特性: Java DB 和 JDBC 4.0
		
http://www.ibm.com/developerworks/cn/java/j-lo-jse65/index.html 长久以来,由于大量(甚至几乎所有)的 Java 应用都依赖于数据库,如何 ...
 - 【Java SE】如何用Java实现冒泡排序
		
摘要: 作为一名Java开发工程师,手头如果不会几个常见的排序算法,怎么可能经过笔试题这一关呢.据我所知,许多大型的公司的笔试题都有排序题,那我们先从最简单的排序:冒泡排序开始,以后几篇博客将继续更新 ...
 - [零基础学JAVA]Java SE基础部分-01. Java发展及JDK配置
		
转自:http://redking.blog.51cto.com/27212/114976 重点要会以下两个方面: 1. 抽象类与接口 2. API==>类集 这是两个最重要部分,这两个部分理解 ...
 - Java SE基础知识
		
Java SE面试题 目录 Java SE基础 基本语法 数据类型 关键字 面向对象 集合 集合类概述 Collection接口 List Set Map Java SE基础 基本语法 数据类型 Ja ...
 - java SE 入门之八大内置基本类型(第二篇)
		
本文采用eclipse 工具演示,如果您对eclipse 工具不了解,请先学习下 eclipse 工具的使用,这个里面只是简单的介绍下输出和注释: 安装完成eclipse 以后,双击进入 后一次点击 ...
 - Java复习总结(二)Java SE 面试题
		
Java SE基础知识 目录 Java SE 1. 请你谈谈Java中是如何支持正则表达式操作的? 2. 请你简单描述一下正则表达式及其用途. 3. 请你比较一下Java和JavaSciprt? 4. ...
 - Java SE、Java EE、Java ME
		
Java SE(Java Platform,Standard Edition).Java SE 以前称为 J2SE.它允许开发和部署在桌面.服务器.嵌入式环境和实时环境中使用的 Java 应用程序.J ...
 
随机推荐
- 图像识别算法--VGG16
			
前言:人类科技就是不断烧开水(发电).丢石头(航天等).深度学习就是一个不断解方程的过程(参数量格外大的方程) 本文内容: 1.介绍VGG16基本原理 2.VGG16 pytorch复现 图像识别算法 ...
 - [前端] html和原生js实现鼠标拖动和触摸拖动以及点击后跟随鼠标移动
			
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
 - C/C++ 的 指针/引用 传参
			
#include <stdio.h> //指针传值 void addOne(int *a) { printf("%8p\n",a); *a = *a+1; } //引用 ...
 - 压测中TPS上不去的几种原因及分析?
			
1. 服务器资源限制:服务器的硬件资源(如 CPU.内存.磁盘)可能不足以处理大量的请求.在高负载情况下,服务器可能无法及时响应所有的请求,导致 TPS 上不去.解决方法可以考虑升级硬件资源或通过负载 ...
 - nginx 基本功能
			
1.nginx简介 官方文档 Nginx是一个高性能WEB服务器,除它之外Apache.Tomcat.Jetty.IIS,它们都是Web服务器,或者叫做WWW(World Wide Web)服务器,相 ...
 - 科技大厂、手机厂商、企服领域齐发力,手机智能体成AI Agent新趋势
			
AI Agent涌向移动终端,手机智能体势不可挡 还没搞清楚什么是AI Agent,手机Agent就已经横空出世 AIGC为何涌向移动端?背后有哪些逻辑?什么是手机智能体?一文看明白 科技大厂.手机厂 ...
 - python Ai 应用开发基础训练,字符串,字典,文件
			
-------------------------------------- 编程能是大模型应用的天花板............................................. ...
 - vscode 合并分支 举例 master merge dev
			
举例 将 dev 开发线 合并到 master 1 确定你在dev线,将dev代码改动全部提交 2 切换master,确定是最新代码,不确定就pull下,选择合并分支,见上图 3 在下拉的提示框中选择 ...
 - AOSP-刷机
			
准备 1.AOSP源码下载 可以参考AOSP下载且编译 这里我下载的是android-12.1.0_r5的AOSP源码 2.下载驱动 因为我下载的是android-12.1.0_r5的AOSP源码,因 ...
 - Mysql中数据类型括号中的数字代表的含义
			
相信大家不管是看别人的代码,还是自己的代码总会在定义表的数据类型时,会需要在数据类型后面加一个括号,里面写一个参数,例如int(3),smallint(5),char(5)等,但是括号里面的数字到底是 ...