Java:无符号数

时间:2009-10-08 19:43:56

标签: java unsigned primitive-types

Java中有没有办法使用像(My)SQL这样的无符号数字?

例如:我想使用一个8位变量(byte),其范围如下:0 ... 256;而不是-128 ... 127

7 个答案:

答案 0 :(得分:9)

不,除了char(有效值为0-65535)之外,Java没有任何无符号基本类型。这是一种痛苦(特别是byte),但就是这样。

通常你要么坚持相同的大小,要么为“高”数字溢出为负数,要么使用更宽的类型(例如shortbyte)并应对额外的内存要求。

答案 1 :(得分:3)

您可以使用类来模拟无符号数。例如

public class UInt8 implements Comparable<UInt8>,Serializable
   {
   public static final short MAX_VALUE=255;
   public static final short MIN_VALUE=0;
   private short storage;//internal storage in a int 16

   public UInt8(short value)
      {
      if(value<MIN_VALUE || value>MAX_VALUE) throw new IllegalArgumentException();
      this.storage=value;
      }

   public byte toByte()
      {
      //play with the shift operator ! << 
      }
  //etc...
   }

答案 2 :(得分:2)

您可以使用带符号的数字,就好像它们是未签名的一样。大多数操作保持不变,有些需要修改。请参阅this post

答案 3 :(得分:2)

在内部,你不应该使用较小的值 - 只需使用int。据我了解,使用较小的单位只能减慢速度。它不会节省内存,因为内部Java使用系统的字大小来存储所有存储空间(它不会打包文字)。

但是,如果您使用较小尺寸的存储单元,则必须为每次操作屏蔽它们或进行范围检查。

注意到char(任何操作)char产生一个int?他们真的不希望你使用这些其他类型。

例外是数组(我相信它会被打包)和I / O你可能会发现使用较小的类型有用......但是屏蔽也可以。

答案 4 :(得分:1)

不,你不能改变它。如果你需要大于127的东西,请选择大于一个字节的东西。

答案 5 :(得分:0)

如果您需要优化存储空间(例如大型矩阵),您可以使用负数编码更大的正数,以节省空间。然后,您必须移动数值以在需要时获取实际值。例如,我只想操纵短正数。这是如何在Java中实现的:

        short n = 32767;
        n = (short) (n + 10);
        System.out.println(n);     
        int m = (int) (n>=0?n:n+65536); 
        System.out.println(m);

因此当短整数超出范围时,它变为负数。但是,至少可以将此数字存储为16位,并通过添加移位值(可以编码的不同值的数量)来恢复其正确的值。应该以更大的类型恢复该值(在我们的例子中为int)。这可能不是很方便,但我发现在我的情况下也是如此。

答案 6 :(得分:0)

我对Java和编程都很陌生。 然而,最近我遇到了无条件值的相同情况。

我花了大约两个星期来编写我想到的所有东西,但我是一个完全的菜鸟,所以你可以花更少的钱。

一般的想法是创建接口,我将其命名为:UnsignedNumber<Base, Shifted>并在实现抽象AbstractUnsigned<Base, Shifted, Impl extends AbstractUnsigned<Base, Shifted, Impl>>类时扩展Number.class。

因此,Base参数化类型表示基本类型,Shifted表示实际Java类型。 Impl是实现此抽象类的快捷方式。

大部分时间都使用Java 8 Lambdas的样板和内部私有类和安全过程。重要的是在减法或负加法等数学运算产生零限制时实现无符号的行为:向后溢出上限符号。

最后,为工厂和实现子类编写代码还需要几天时间。

到目前为止,我知道: UByte和MUByte UShort和MUShort UInt和MUInt ......等等。

他们是AbstractUnsigned的后代: UByte或MUByte扩展AbstractUnsigned<Byte, Short, UByte>AbstractUnsigned<Byte, Short, MUByte> UShort或MUShort延长AbstractUnsigned<Short, Integer, UShort>AbstractUnsigned<Short, Integer, MUShort> ...等

一般的想法是将无符号上限作为移位(转换)类型和负值的代码转换,因为它们不是来自零,而是来自无符号上限。

更新: (感谢Ajeans善意和礼貌的指示)

/**
* Adds value to the current number and returns either
* new or this {@linkplain UnsignedNumber} instance based on
* {@linkplain #isImmutable()}
*
* @param value value to add to the current value
* @return new or same instance
* @see #isImmutable()
*/
public Impl plus(N value) {
    return updater(number.plus(convert(value)));
}

这是AbstractUnsigned<N, Shifted, Impl>的外部可访问方法(或之前AbstractUnsigned<Base, Shifted, Impl>之前所说的); 现在,对于引擎盖下的工作:

private Impl updater(Shifted invalidated){
    if(mutable){
        number.setShifted(invalidated);
        return caster.apply(this);
    } else {
        return shiftedConstructor.apply(invalidated);
    }
}

在上述私有方法中,mutableprivate final boolean的{​​{1}}。 AbstractUnsigned是内部私有类之一,负责将number转换为Base,反之亦然。 与之前的“我去年夏天所做的事情相对应的重要事项” 是两个内部对象:Shiftedcaster

shiftedConstructor

如果final private Function<UnsignedNumber<N, Shifted>, Impl> caster; final private Function<Shifted, Impl> shiftedConstructor; 的当前实现实例,这些是将N(或Base)强制转换为Shifted或创建新Impl实例的参数化函数是不可变的。

AbstractUnsigned<>

在此片段中显示了Shifted plus(Shifted value){ return spawnBelowZero.apply(summing.apply(shifted, value)); } 对象的添加方法。我们的想法是始终在内部使用number,因为不确定何时会产生“原始”类型的正限制。 Shifted是一个内部参数化字段,其中包含整个shifted的值。另外两个AbstractUnsigned<>衍生对象如下:

Function<>

前者执行两个final private BinaryOperator<Shifted> summing; final private UnaryOperator<Shifted> spawnBelowZero; 值的添加。后者在零转换下执行产卵。

现在来自Shifted的工厂样板之一'地狱'的一个例子专门针对前面提到的AbstractUnsigned<Byte, Short> spawnBelowZero

UnaryOperator<Shifted>

如果..., v-> v >= 0 ? v : (short) (Math.abs(Byte.MIN_VALUE) + Byte.MAX_VALUE + 2 + v), ... 为正数,则不会发生任何事情,并返回原始值。否则:需要计算Shifted v类型的上限Base并加上该值为负值Byte。如果,假设为v,则v == -8将生成Math.abs(Byte.MIN_VALUE),而128将生成Byte.MAX_VALUE,这会127 + 1获得原始版本由于我得到了那个被符号位切断的限制,并且那个理想的255就在那里。但是,第一个负值 实际上是256,这就是256再次或+1的原因。最后,+2 255 + 2 + v给出了-8255 + 2 + (-8)

或以更直观的方式:

249

最后完成所有这些:这绝对不会减轻您的工作或节省内存字节,但在需要时您会有一个非常理想的行为。并且您可以与任何其他0 1 2 3 ... 245 246 247 248 249 250 251 252 253 254 255 256 -8 -7 -6 -5 -4 -3 -2 -1 子类一起使用该行为。作为Number.class的子类的AbstractUnsigned本身提供了所有便利方法和常量 类似于其他“原生”Number.class子类,包括Number.classMIN_VALUE等等,例如,我编写了名为MAX_VALUE的可变子类的便捷方法,它执行最简单的操作makeDivisibileBy(Number n)

我最初的努力是表明,即使是像我这样的菜鸟,也可以编码。我编写该课程时的最初努力是获得方便的多功能工具以便持续使用。