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位)的二进制比特流数据如何进行大数的数值计算?的更多相关文章

  1. 【Java SE】如何用Java实现直接选择排序

    摘要:直接选择排序属于选择排序的一种,但是它的排序算法比冒泡排序的速度要快一些,由于它的算法比较简单,所以也比较适合初学者学习掌握. 适宜人群:有一定Java SE基础,明白Java的数据类型,数组的 ...

  2. 【Java SE】如何用Java实现插入排序

    摘要:前面三期分别写了三篇简单排序的算法,今天来讲一点稍微难一点的排序算法-----插入排序. 基本思想: 设n个数据已经按照顺序排列好(假定从小排到大). 输入一个数据x,将其放在恰当的位置,使其顺 ...

  3. 【Java SE】如何用Java实现反转排序

    摘要:反转排序是将原先已经排序好了的重新排序,是原来的数组元素的顺序反转过来.假设原来的数组顺序是{6,5,4,3,2,1},反转之后的顺序就是{1,2,3,4,5,6}.这个排序的算法不是很难,代码 ...

  4. Java SE 6 新特性: Java DB 和 JDBC 4.0

    http://www.ibm.com/developerworks/cn/java/j-lo-jse65/index.html 长久以来,由于大量(甚至几乎所有)的 Java 应用都依赖于数据库,如何 ...

  5. 【Java SE】如何用Java实现冒泡排序

    摘要: 作为一名Java开发工程师,手头如果不会几个常见的排序算法,怎么可能经过笔试题这一关呢.据我所知,许多大型的公司的笔试题都有排序题,那我们先从最简单的排序:冒泡排序开始,以后几篇博客将继续更新 ...

  6. [零基础学JAVA]Java SE基础部分-01. Java发展及JDK配置

    转自:http://redking.blog.51cto.com/27212/114976 重点要会以下两个方面: 1. 抽象类与接口 2. API==>类集 这是两个最重要部分,这两个部分理解 ...

  7. Java SE基础知识

    Java SE面试题 目录 Java SE基础 基本语法 数据类型 关键字 面向对象 集合 集合类概述 Collection接口 List Set Map Java SE基础 基本语法 数据类型 Ja ...

  8. java SE 入门之八大内置基本类型(第二篇)

    本文采用eclipse 工具演示,如果您对eclipse 工具不了解,请先学习下 eclipse 工具的使用,这个里面只是简单的介绍下输出和注释: 安装完成eclipse 以后,双击进入 后一次点击 ...

  9. Java复习总结(二)Java SE 面试题

    Java SE基础知识 目录 Java SE 1. 请你谈谈Java中是如何支持正则表达式操作的? 2. 请你简单描述一下正则表达式及其用途. 3. 请你比较一下Java和JavaSciprt? 4. ...

  10. Java SE、Java EE、Java ME

    Java SE(Java Platform,Standard Edition).Java SE 以前称为 J2SE.它允许开发和部署在桌面.服务器.嵌入式环境和实时环境中使用的 Java 应用程序.J ...

随机推荐

  1. 手把手教你用 NebulaGraph AI 全家桶跑图算法

    前段时间 NebulaGraph 3.5.0 发布,@whitewum 吴老师建议我把前段时间 NebulaGraph 社区里开启的新项目 ng_ai 公开给大家. 所以,就有了这个系列文章,本文是该 ...

  2. 一文了解 NebulaGraph 上的 Spark 项目

    本文首发于 Nebula Graph Community 公众号 最近我试着搭建了方便大家一键试玩的 Nebula Graph 中的 Spark 相关的项目,今天就把它们整理成文分享给大家.而且,我趟 ...

  3. Linux安装Docker教程

    介绍 Docker利用Linux核心中的资源分脱机制,例如cgroups,以及Linux核心名字空间(name space),来创建独立的软件容器(containers).可以在单一Linux实体下运 ...

  4. 简单封装 Flurl

    FlurlHttpClient类 public class FlurlHttpClient { private readonly FlurlClient client; public FlurlHtt ...

  5. Java 多线程------测试 Thread中的常用方法 + 线程的优先级:

    1 package com.bytezero.threadexer; 2 3 import javax.sound.midi.Soundbank; 4 5 /** 6 * 测试 Thread中的常用方 ...

  6. C++ //常用查找算法 find_if

    1 //常用查找算法 find_if 2 #include<iostream> 3 #include<string> 4 #include<vector> 5 #i ...

  7. HW学习笔记

    栈库分离方法注意事项: 所有用户输入数据需要进行分离过滤,不能遗漏.选择安全的过滤函数 如 mysql_real_escape_string(),避免过滤不严格导致注入 SQL查询模板需要设计安全,米 ...

  8. PDF/Excel文件预览功能完整实现-java版本

    新需求 最近接到一个新的需求,说是之前直接下载的PDF文件或者是Excel文件,现在不能直接下载,需要实现在线预览功能. 前端人员拿到这个需求后,去看了一下以前的代码,以前调用的下载接口和PDF文件预 ...

  9. gyroflow.xyz - 视频防抖 支持相机 gopro 不支持手机视频 - 软件推荐

    gyroflow.xyz - 视频防抖 支持相机 gopro 不支持手机视频 - 软件推荐 https://gyroflow.xyz/ https://github.com/gyroflow/gyro ...

  10. day03-2-应用线程02

    JavaGUI-坦克大战03-2 7.线程的应用02 7.3.坦克大战4.0版 坦克大战4.0版 增加功能: 功能1.让敌人的坦克也能够发射子弹(可以有多个子弹) 功能2.当我方坦克集中敌人坦克时,敌 ...