Pregunta

¿Hay una manera de Java para utilizar números sin signo igual que en (Mi) de SQL?

Por ejemplo: Quiero usar una variable de 8 bits (byte) con un rango como: 0 ... 256; en lugar de -128 ... 127.

¿Fue útil?

Solución

No, Java no tiene ningún tipo primitivo sin firmar, aparte de char (que tiene valores 0-65535, con eficacia). Es un dolor (particularmente para byte), pero esa es la manera que es.

Por lo general, ya sea seguir con el mismo tamaño, y el desbordamiento en negativos para los números "altos" o bien utiliza el tipo más amplio (por ejemplo short para byte) y hacer frente a los requisitos de memoria adicionales.

Otros consejos

Puede utilizar una clase para simular un número sin signo. Por ejemplo

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...
   }

Puede utilizar números con signo sobre todo como si fueran sin firmar. La mayoría de las operaciones se mantienen igual, algunos necesitan ser modificados. Ver este post .

A nivel interno, no deberías estar usando los valores más pequeños - sólo tiene que utilizar int. Como yo lo entiendo, el uso de unidades más pequeñas no hace más que retrasar las cosas. No guarda la memoria porque internamente Java utiliza tamaño de palabra del sistema para todo el almacenamiento (que no empacar palabras).

Sin embargo, si se utiliza una unidad de almacenamiento de tamaño más pequeño, tiene que enmascarar ellos o prueba de alcance o algo para cada operación.

siempre el aviso de que char (ninguna operación) carbón produce un int? Ellos realmente no esperan que usted utilice estos otros tipos.

Las excepciones son matrices (que creo que va a hacer las maletas) y E / S donde se podrían encontrar utilizando un tipo más pequeño, pero útil ... enmascaramiento funcionará tan bien.

No, no se puede cambiar eso. Si necesita algo más grande que 127 elegir algo más grande que un byte.

Si usted necesita para optimizar su almacenamiento (por ejemplo matriz grande) puede u puede codificar grandes números positivos con los números negativos, por lo que para ahorrar espacio. Entonces, usted tiene que cambiar el valor del número para obtener el valor real cuando sea necesario. Por ejemplo, quiero manipular sólo números positivos cortos. Aquí cómo esto es posible en Java:

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

Así que cuando un entero corto excede el alcance, se convierte en negativo. Sin embargo, al menos se puede guardar este número en 16 bits, y restaurar su valor correcto mediante la adición de valor de desplazamiento (número de valores diferentes que pueden codificarse). El valor debe ser restaurada en un tipo más grande (int en nuestro caso). Esto puede no ser muy conveniente, pero me parece que es lo que en mi caso.

Soy bastante nuevo en Java y la programación. Sin embargo, me encontré con la misma situación recientemente la necesidad de valores sin signo.

Me tomó alrededor de dos semanas para codificar todo lo que tenía en mente, pero yo soy un novato total de, por lo que podría pasar mucho menos.

La idea general es crear interfaz, he nombrado:. UnsignedNumber<Base, Shifted> y extender Number.class mientras que la implementación de una clase abstracta AbstractUnsigned<Base, Shifted, Impl extends AbstractUnsigned<Base, Shifted, Impl>>

Por lo tanto, la base de tipo parametrizado representa el tipo base, desplazada representa el tipo real de Java. Impl es un acceso directo para la aplicación de esta clase abstracta.

La mayor parte del texto modelo consumido momento de Java 8 lambdas y clases privadas internas y procedimientos de seguridad. Lo importante era lograr el comportamiento de firmar cuando la operación matemática como la sustracción o adición negativa genera el límite cero:. Desbordar el límite superior firmado revés

Por último, se tomó un par de días para fábricas de código y subclases de aplicación.

Hasta ahora he saber: UBYTE y MUByte Ushort y MUShort UInt y MUInt ... etc.

Son descendientes de AbstractUnsigned: UBYTE o MUByte extienden AbstractUnsigned<Byte, Short, UByte> o AbstractUnsigned<Byte, Short, MUByte> Ushort o MUShort extienden AbstractUnsigned<Short, Integer, UShort> o AbstractUnsigned<Short, Integer, MUShort> ... etc.

La idea general es tomar como límite superior sin signo cambiado (fundido) el tipo y código de transposición de valores negativos, ya que estaban por venir no de cero, pero el límite superior sin firmar.

ACTUALIZACIÓN: (Gracias a Ajeans direcciones amable y cortés)

/**
* 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)));
}

Este es un método accesible desde el exterior de AbstractUnsigned<N, Shifted, Impl> (o como se dijo antes AbstractUnsigned<Base, Shifted, Impl>); Ahora, para el trabajo bajo el capó:

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

En el método privado mutable anterior es una private final boolean de un AbstractUnsigned. number es una de las clases privadas internas que se encarga de transformar Base a Shifted y viceversa. Lo que importa en correspondencia con las anteriores ' lo que hice la última parte del verano ' es de dos objetos internos: caster y shiftedConstructor:

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

Estas son las funciones parametrizadas a N emitidos (o Base) a Shifted o para crear una nueva instancia Impl si la instancia actual de la aplicación AbstractUnsigned<> es inmutable.

Shifted plus(Shifted value){
    return spawnBelowZero.apply(summing.apply(shifted, value));
}

En este fragmento se muestra el método de adición del objeto number. La idea era utilizar siempre Shifted internamente, porque no se sabe cuándo se generaron los límites positivos del tipo 'original'. shifted es un campo parametrizado interna que lleva el valor de todo el AbstractUnsigned<>. Los otros objetos derivados dos Function<> se dan a continuación:

final private BinaryOperator<Shifted> summing;
final private UnaryOperator<Shifted> spawnBelowZero;

El ex realiza una suma de dos valores Shifted. Y el segundo realiza el desove por debajo de cero transposición.

Y ahora un ejemplo de uno de los demonios '' los boilerplates fábrica para AbstractUnsigned<Byte, Short> específicamente para el mencionado antes spawnBelowZero UnaryOperator<Shifted>:

...,
         v-> v >= 0
         ? v
         : (short) (Math.abs(Byte.MIN_VALUE) + Byte.MAX_VALUE + 2 + v),
...

Si Shifted v hay nada positivo que realmente sucede y se devuelve el valor original. De lo contrario: hay una necesidad de calcular el límite superior del tipo Base que es Byte y añadir hasta que v valor negativo. Si, digamos, v == -8 continuación Math.abs(Byte.MIN_VALUE) producirá 128 y Byte.MAX_VALUE producirá 127 que da 255 + 1 para obtener el límite superior original que fue cortado de por el bit de signo, como llegué a eso, y el 256 tan deseable está en el lugar . Pero el valor negativo primera es de hecho que 256 por eso +1 de nuevo o +2 en total. Finalmente, 255 + 2 + v que es -8 da 255 + 2 + (-8) y 249

O de una manera más visual:

0 1 2 3 ... 245 246 247 248 249 250 251 252 253 254 255 256
                             -8  -7  -6  -5  -4  -3  -2  -1

Y para finalizar todo eso: esto definitivamente no alivia su trabajo o ahorra bytes de memoria, pero tiene un comportamiento más o menos deseable cuando se necesita. Y puede utilizar ese comportamiento prácticamente con cualquier otro subclases Number.class. AbstractUnsigned ser subclase de Number.class sí mismo proporciona todos los métodos de conveniencia y constantes similar a otras subclases Number.class 'nativos', incluyendo MIN_VALUE y MAX_VALUE y mucho más, por ejemplo, codifiqué método de conveniencia para las subclases mutables llamados makeDivisibileBy(Number n) que lleva a cabo la operación más simple de value - (value % n).

Mi esfuerzo inicial aquí era mostrar que incluso un novato, tal como soy, puede codificarlo. Mi esfuerzo inicial cuando estaba codificación que la clase era conseguir convenientemente herramienta versátil para el uso constante.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top