`
greenmoon
  • 浏览: 48601 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java中处理无符号数字的工具类

 
阅读更多

在大型的商业系统中需要跟其他各种语言开发的子系统或者组件通信,其他的系统可能会支持无符号数字,比如c语言开发的服务系统,但java都是有符号的,往往会造成传递过来的unsigned数字被转换为负数,造成逻辑上的错误,java 6是不会支持unsigned数字了,因此需要自己去做一些转换。代码如下:

import java.math.BigInteger;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * java语言数字工具类,支持把其他语言的无符号的数字转换为java语言的数字类型,并且不会改变正负号。
 * 
 * java语言的基础数据类型都是有符号,当从其他语言接收到一个无符号的数字时,java语言会使用具有相同字节数的数字类型来接收,并可能改变其符号:
 * 比如: c语言的unsigned int32 值 0xffffffff, java语言的int类型接收后会识别为负数,而这并不是业务上所期望的,因此对于这类数据
 * 需要使用字节数多的数据类型来接收,比如上面的例子需要使用long数据类型来接收,如果是 c语言的unsigned int64值需要使用java的BigInteger来接收。
 * @author greenmoon
 *
 */
public abstract class UnsignedNumberUtil {
	/**
	 * 判断一个byte类型的数字是否为负数,如果为负数需要使用更宽类型的数据类型来接收,比如short,int,long等,一般使用short接收。
	 *
	 * @param value 
	 * @return
	 */
	public static boolean needWiden(byte value){
		// 0x80 = 10000000,即2的7次方,对于byte型数字来说就是符号位,如果符号位为1,则该数字为负数
		// 0x80也就是Byte.MIN_VALUE
		return (value & 0x80) == 0x80;
	}
	/**
	 * 判断一个short类型的数字是否为负数,如果为负数需要使用更宽类型的数据类型来接收,比如int,long等,一般使用int接收。
	 *
	 * @param value 
	 * @return
	 */
	public static boolean needWiden(short value){
		// 0x80000,即2的15次方,对于int型数字来说就是符号位,如果符号位为1,则该数字为负数
		// 0x8000也就是Short.MIN_VALUE
		return (value & 0x8000) == 0x8000;
	}
	/**
	 * 判断一个int类型的数字是否为负数,如果为负数需要使用更宽类型的数据类型来接收,使用long接收。
	 *
	 * @param value 
	 * @return
	 */
	public static boolean needWiden(int value){
		// 0x80000000,即2的31次方,对于int型数字来说就是符号位,如果符号位为1,则该数字为负数
		// 0x80000000也就是Integer.MIN_VALUE
		return (value & 0x80000000) == 0x80000000;
	}
	/**
	 * 判断一个long类型的数字是否为负数,如果为负数需要BigInteger,这是因为java基础类型中字节数最多的就是long了,超过long表示范围的需要使用java库提供的
	 * BigInteger 对象类型
	 *
	 * @param value 
	 * @return
	 */
	public static boolean needWiden(long value){
		// 0x8000000000000000L,即2的63次方,对于int型数字来说就是符号位,如果符号位为1,则该数字为负数
		// 0x8000000000000000L也就是Long.MIN_VALUE
		// 注意后面那个L,如果没有这个L,java会认为这个数字为int类型
		return (value & 0x8000000000000000L) == 0x8000000000000000L;
	}
	/**
	 * byte类型转换为short类型,如果是value>0则直接返回,java语言自动支持转换,如果value<0则需要处理符号位:
	 * @param value
	 * @return
	 */
	public static short toUnsignedByteValue(byte value){
		if(!needWiden(value)){
			return value;
		}
		short wideValue = value;
		// 使用 与 运算把高为字节设置为0,符号位为0,该数字为正数
		return (short)(wideValue & 0xff);
	}
	/**
	 * short类型转换为int类型,如果是value>0则直接返回,java语言自动支持转换,如果value<0则需要处理符号位:
	 * @param value
	 * @return
	 */
	public static int toUnsignedShortValue(short value){
		if(!needWiden(value)){
			return value;
		}
		// 使用 与 运算把高为字节设置为0,符号位为0,该数字为正数
		int wideValue = value;
		return wideValue & 0xffff;
	}
	/**
	 * int类型转换为long类型,如果是value>0则直接返回,java语言自动支持转换,如果value<0则需要处理符号位:
	 * @param value
	 * @return
	 */
	public static long toUnsignedIntValue(int value){
		if(!needWiden(value)){
			return value;
		}
		long wideValue = value;
		// 使用 与 运算把高为字节设置为0,符号位为0,该数字为正数
		// 注意后面那个L,如果没有这个L,java会认为这个数字为int类型,在运算过程中他会自动把他转换为long类型,那么最终的返回的值就还是负数,这是由于字节少的数字类型转换为字节多的类型时太会
		// 自动用符号位填充高位字节,,举个例子,
		// 例子1
		// int value = 100;
		// long lv = value; 此时低4个字节填充的是100,而高4个字节是0
		// 例子3
		// int value = 0xf0000000;
		// long lv = value; 此时低4个字节是0xf0000000, 而高4个字节是1,因为0xf0000000的符号位是1
		// 至于为什么是这样,这里不再解释,考虑一下计算机内部负数是用补码表示的这一原则
		return wideValue & 0xffffffffL;
	}
	/**
	 * long类型转换为BigInteger类型,如果是value>0则直接返回,java语言自动支持转换,如果value<0则需要处理符号位:
	 * @param value
	 * @return
	 */
	public static BigInteger toUnsignedLongValue(long value){
		if(!needWiden(value)){
			return BigInteger.valueOf(value);
		}
		// long型为8个字节,已经是占用字节最多的类型了,需要使用BigInteger来表示unsigned long了
		// 原理是获取long类型的字节数组,并把该数组作为BigInteger构造参数,然后构建BigInteger,
		// BigInteger所接收的byte数字是用大尾端表示的,因此在获取long的字节数组时使用ByteBuffer这个工具,
		// 关于大尾端、小尾端,请参见ByteOrder,或者一些操作系统相关的书籍
		ByteBuffer buffer = ByteBuffer.allocate(Long.SIZE/Byte.SIZE);
		buffer.order(ByteOrder.BIG_ENDIAN);
		buffer.putLong(value);
		return new BigInteger(1,buffer.array());
	}
}

 

 

分享到:
评论

相关推荐

    java替换字符串中的符号

    在Java编程语言中,处理字符串是一项常见的任务,尤其是在文本处理、数据清洗以及各种与字符串相关的操作中。本文将深入探讨如何在Java中替换字符串中的特定符号,并解析代码示例,以便更好地理解其工作原理。 ### ...

    无符号整数表达式的判定

    在计算机编程领域,尤其在Java语言中,无符号整数表达式的判定是一项基础且重要的任务。无符号整数(Unsigned Integer)指的是在二进制表示下没有符号位的整数类型,它只能表示非负数值,范围从0到最大值,这通常取...

    java工具类——验证码(VerifyCode)

    在Java中,我们可以创建一个工具类来生成这种随机验证码,以增强系统安全性。下面我们将深入探讨如何实现这样的验证码工具类及其原理。 1. **验证码生成原理** - 验证码通常由一组随机字符组成,可以是数字、字母...

    Java 中文排序 使用pinyin4j组件

    5. **特殊字符处理**:对于无法转换成拼音的特殊字符,如标点符号、数字等,`pinyin4j`会返回空字符串。在实际应用中,可能需要额外的处理逻辑,比如将它们放到最后或根据其他规则排序。 6. **性能优化**:如果需要...

    Java开发技术大全(500个源代码).

    invokeMethod.java 同一个类中调用方法示例 invokeOther.java 类的外部调用方法示例 invokeStaticMethod.java 调用静态方法示例 localVariable.java 演示局部变量 localVSmember.java 局部变量与成员变量同名...

    java类对正则表达式的处理

    在Java编程语言中,正则表达式是一种强大的文本处理工具,用于模式匹配、搜索和...总之,这个Java类简化了Java中正则表达式的应用,为开发者提供了方便快捷的验证和处理功能,是Java项目中处理字符串模式匹配的好帮手。

    一个java正则表达式工具类源代码.zip(内含Regexp.java文件)

    以前写了一个java的正规表达式的java工具类,分享一下,有用到的欢迎下载使用。 如果你有常用的定义好的,且测试通过的正规表达式,欢迎跟贴,也让我享用一下 . 类中用到了 jakarta-oro-2.0.jar 包,请大家自己在 ...

    正则表达式验证工具Java

    正则表达式是一种强大的文本处理工具,广泛应用于数据验证、搜索和替换等场景。在Java中,正则表达式是通过java.util.regex包提供的API来实现的。本工具"正则表达式验证工具Java"专注于帮助开发者测试和验证他们的...

    JAVA_MAC地址校验和转换

    以上内容涵盖了Java中处理MAC地址的一些核心概念和操作。通过这些技术,开发人员可以在各种场景下对MAC地址进行有效的管理和保护,例如在网络认证、设备追踪或者数据安全等方面。请注意,实际应用中应根据项目需求...

    JAVA中文乱码过滤器

    - **InputStreamReader/OutputStreamWriter**:Java中用于处理字符流的类,可以指定字符集进行读写操作,是解决乱码问题的关键工具。 - **Charset类**:Java提供的一套字符集接口,可以获取系统支持的所有字符集,...

    JAVA11培训课堂 2020版 部分笔记.doc

    首先,BigInteger类是Java提供的无符号整数类,能够处理任意大的整数。在示例代码中,我们创建了两个BigInteger对象`numA`和`numB`,并进行了加法、乘法、乘方和除法运算。`add()`方法用于加法,`multiply()`方法...

    Core Java

    11. **标识符**:标识符用于命名变量、方法和类,以字母、下划线或美元符号开头,后续可跟字母、数字或下划线。 掌握这些基础概念和规则是学习Core Java的起点,随着深入学习,还将涉及异常处理、输入/输出、集合...

    java 移位运算符的资源

    Java 移位运算符是编程语言中用于处理二进制位的一种高效操作方式,它们能够对整数类型(byte, short, int, long)的值进行左移、右移和无符号右移操作。理解这些运算符对于优化代码和深入理解计算机底层工作原理至...

    王宫花园 Java GUI课程设计

    - 对Java GUI编程的理解加深,包括组件使用、事件处理和类的设计。 - 提高了解决实际问题的能力,从无到有构建一个可用的应用程序。 这个Java GUI课程设计项目,虽然可能只是一个简单的计算器,但它是理解Java ...

    JAVA选择题复习.txt

    - Java中的位移运算符包括`&gt;&gt;`(右移)、`(左移)和`&gt;&gt;&gt;`(无符号右移)。 #### 19. 位运算操作 - `&gt;&gt;&gt;`为无符号右移运算符,用于将二进制数进行右移操作,高位补零。 #### 20. 浮点数取模运算 - 浮点数也可以...

    java重要知识点总结

    - **位运算符**:`~`(按位取反)、`&`(按位与)、`|`(按位或)、`^`(按位异或)、`(左移)、`&gt;&gt;`(右移)、`&gt;&gt;&gt;`(无符号右移) #### 10. 控制流语句 Java 提供了多种控制流语句,包括条件语句、循环语句和...

    java类文件结构(笔记).docx

    无符号数是基本的数据类型,它们是不包含负值的数字,以u1、u2、u4、u8表示1个字节、2个字节、4个字节和8个字节的大小。无符号数可以用来表示数值、索引引用、数量以及通过UTF-8编码构建的字符串。例如,字符串常量...

    java生成UUID通用唯一识别码.docx

    在Java中,UUID可以通过`java.util.UUID`类来生成。这个类提供了多种生成UUID的方法。例如,`UUID.randomUUID()`方法可以生成一个基于时间的UUID,这是最常见的类型,它结合了当前时间戳、随机数和机器标识,确保...

    经典Java趣味入门

    - **JDK提供的Java基本包**:如`java.lang`、`java.util`等,提供了一系列常用的功能和工具类。 **2.1.3 包引入语句** 使用`import`语句来引入其他包中的类,便于在当前类中使用。例如: ```java import java....

Global site tag (gtag.js) - Google Analytics