4

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

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

4

7 回答 7

9

不,Java 没有任何无符号原始类型char(有效值为 0-65535)。这是一种痛苦(尤其是对于byte),但事实就是如此。

通常,您要么坚持使用相同的大小,并将“高”数字溢出为负数,要么使用更广泛的类型(例如shortfor byte)并处理额外的内存需求。

于 2009-10-08T19:46:24.943 回答
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...
   }
于 2009-10-08T19:51:39.147 回答
2

大多数情况下,您可以像使用无符号数一样使用有符号数。大多数操作保持不变,有些需要修改。看到这个帖子

于 2009-10-08T19:52:35.540 回答
2

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

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

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

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

于 2009-10-08T20:17:29.920 回答
1

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

于 2009-10-08T19:47:32.570 回答
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)恢复。这可能不是很方便,但我发现在我的情况下是如此。

于 2013-07-04T13:55:34.683 回答
0

我对 Java 和编程很陌生。然而,我最近遇到了同样的情况,需要无符号值。

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

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

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

大多数时间消耗 Java 8 Lambda 的样板文件和内部私有类和安全程序。重要的是当减法或负加法等数学运算产生零极限时实现无符号行为:向后溢出有符号上限。

最后,又花了几天时间编写工厂代码和实现子类。

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

它们是 AbstractUnsigned 的后代:UByte 或 MUByte extendAbstractUnsigned<Byte, Short, UByte>AbstractUnsigned<Byte, Short, MUByte> UShort 或 MUshort extendAbstractUnsigned<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);
    }
}

在上面的私有方法mutable中是private final boolean一个AbstractUnsignednumber是负责转换为的内部私有类之一,Base反之亦然Shifted。与之前的“我去年夏天所做的部分”相对应的是两个内部对象:castershiftedConstructor

final private Function<UnsignedNumber<N, Shifted>, Impl> caster;
final private Function<Shifted, Impl> shiftedConstructor;

如果 的当前实现实例是不可变的,则这些是要转换N(或Base)到Shifted或创建新实例的参数化函数。ImplAbstractUnsigned<>

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类型的上限 isByte并加起来为负值v。如果,比方说,v == -8那么Math.abs(Byte.MIN_VALUE)将产生并将128产生Byte.MAX_VALUE+ 1 以获得被符号位削减的原始上限,正如我所知道的那样,并且如此理想就在这个地方。但第一个负值实际上是这就是为什么再次或完全如此。最后,这是给和127255256256+1+2255 + 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.class,包括MIN_VALUEandMAX_VALUE以及更多,例如,我为可变子类编写了便利方法,调用makeDivisibileBy(Number n)它执行最简单的value - (value % n).

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

于 2016-01-04T23:21:26.480 回答