Question

Est-il possible en Java d'utiliser les numéros non signés comme dans (My) SQL?

Par exemple: Je veux utiliser un avec une gamme comme variable de 8 bits (byte): 0 ... 256; au lieu de -128 ... 127.

Était-ce utile?

La solution

Non, Java n'a pas d'types primitifs non signés en dehors de char (qui a des valeurs 0-65535, efficace). Il est une douleur (en particulier pour byte), mais c'est la façon dont il est.

En général, vous soit coller avec la même taille, et le débordement dans les négatifs pour le nombre « élevé », ou utiliser le type plus large (par exemple de short pour byte) et faire face aux exigences de mémoire supplémentaires.

Autres conseils

Vous pouvez utiliser une classe pour simuler un nombre non signé. Par exemple

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

Vous pouvez utiliser la plupart des nombres signés comme si elles étaient non signés. La plupart des opérations restent les mêmes, certains ont besoin d'être modifiés. Voir cette post.

En interne, vous ne devriez pas utiliser les valeurs plus petites - il suffit d'utiliser int. Si je comprends bien, en utilisant des unités plus petites choses ne rien ralentir. Il n'a pas d'économiser de la mémoire interne parce que Java utilise la taille de texte de système pour tout le stockage (il ne sera pas emballer mots).

Toutefois, si vous utilisez une plus petite unité de stockage de taille, il doit les masquer ou contrôle de plage ou quelque chose pour chaque opération.

Avez-vous remarqué que char (toute opération) char donne un int? Ils vraiment ne vous attendez pas à utiliser ces types.

Les exceptions sont des tableaux (qui, je crois obtenir emballés) et E / S où vous pourriez trouver en utilisant un type plus petit utile ... mais masquage fonctionnera aussi bien.

Non, vous ne pouvez pas changer cela. Si vous avez besoin de quelque chose de plus de 127 choisir quelque chose de plus qu'un octet.

Si vous avez besoin pour optimiser votre stockage (par exemple grande matrice), vous pouvez u pouvez coder plus grand nombres positifs avec un nombre de négatifs, pour ainsi économiser de l'espace. Ensuite, vous devez passer à la valeur numérique pour obtenir la valeur réelle en cas de besoin. Par exemple, je veux manipuler des nombres positifs courts seulement. Voici comment cela est possible 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);

Alors, quand un nombre entier supérieur à courte portée, il devient négatif. Pourtant, on peut au moins stocker ce numéro sur 16 bits, et de restaurer sa valeur correcte en ajoutant une valeur de décalage (nombre de valeurs différentes qui peuvent être codée). La valeur doit être rétablie dans un type plus grand (int dans notre cas). Cela peut ne pas être très pratique, mais je trouve qu'il est mon cas.

Je suis tout à fait nouveau à Java et à la programmation. Pourtant, j'ai rencontré la même situation récemment la nécessité de valeurs non signées.

Il m'a fallu environ deux semaines pour coder tout ce que j'avais en tête, mais je suis un noob total pour que vous puissiez passer beaucoup moins.

L'idée générale est de créer une interface, je l'ai nommé. UnsignedNumber<Base, Shifted> et d'étendre Number.class tout en mettant en œuvre une classe abstraite AbstractUnsigned<Base, Shifted, Impl extends AbstractUnsigned<Base, Shifted, Impl>>

Ainsi, la base de type paramétrés représente le type de base, représente Shifted type Java réelle. Impl est un raccourci pour la mise en œuvre de cette classe abstraite.

La plupart du temps consommé de Java boilerplate 8 lambdas et des cours privés et des procédures internes de sécurité. L'important était d'obtenir le comportement de non signé lorsque l'opération mathématique comme la soustraction ou l'addition négative engendre la limite zéro:. Déborder en arrière la limite supérieure signé

Enfin, il a fallu deux jours pour les usines de code et sous-classes de mise en œuvre.

Jusqu'à présent, je sais: UBYTE et MUByte UShort et MUShort UInt et MUInt ... Etc.

Ils sont les descendants de AbstractUnsigned: UBYTE ou MUByte étendent AbstractUnsigned<Byte, Short, UByte> ou AbstractUnsigned<Byte, Short, MUByte> UShort ou MUShort étendent AbstractUnsigned<Short, Integer, UShort> ou AbstractUnsigned<Short, Integer, MUShort> ... etc.

L'idée générale est de prendre la limite supérieure non signé décalé (casted) le type et la transposition de code des valeurs négatives qu'ils devaient venir pas de zéro, mais la limite supérieure non signée.

Mise à jour: (Merci Ajeans de directions gentil et poli)

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

Cette méthode est accessible de l'extérieur de AbstractUnsigned<N, Shifted, Impl> (ou comme il a été dit précédemment AbstractUnsigned<Base, Shifted, Impl>); Maintenant, au travail sous le capot:

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

Dans la méthode ci-dessus mutable privé est un private final boolean d'un AbstractUnsigned. number est l'une des classes privées internes qui se charge de la transformation Base à Shifted et vice versa. Ce qui compte en correspondance avec les précédents ' ce que je faisais partie de l'été dernier est de deux objets internes: caster et shiftedConstructor:

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

Ce sont les fonctions paramétrées exprimés N (ou Base) à Shifted ou pour créer une nouvelle instance de Impl si instance en cours de mise en œuvre du AbstractUnsigned<> est immuable.

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

Dans ce fragment est représenté le procédé en ajoutant de l'objet number. L'idée était d'utiliser toujours Shifted en interne, car il est incertain lorsque les limites positives de type « original » sera donné naissance. shifted est un champ interne paramétré qui porte la valeur de l'ensemble AbstractUnsigned<>. Les autres deux objets dérivés de Function<> sont donnés ci-dessous:

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

L'ancien effectue l'addition de deux valeurs de Shifted. Et celui-ci effectue fraie en dessous de zéro transposition.

Et maintenant un exemple de l'un des spécifiquement pour la cité les boilerplates usine de l'enfer »pour AbstractUnsigned<Byte, Short> avant spawnBelowZero UnaryOperator<Shifted>:

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

si Shifted v est rien de positif qui se passe vraiment et la valeur initiale est renvoyée. Dans le cas contraire: il est nécessaire de calculer la limite supérieure du type Base qui est Byte et ajouter à cette valeur v négative. Si, disons, v == -8 alors Math.abs(Byte.MIN_VALUE) produira 128 et Byte.MAX_VALUE produira 127 qui donne 255 + 1 pour obtenir la limite supérieure d'origine qui a été coupé de par le bit de signe, comme je l'ai que, et si désirable 256 est dans le lieu . Mais la valeur première négative est fait que 256 c'est pourquoi +1 à nouveau ou +2 au total. Enfin, 255 + 2 + v qui est -8 donne 255 + 2 + (-8) et 249

Ou de manière plus visuelle:

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

Et pour finaliser tout cela: cela ne facilite pas vraiment votre travail ou enregistre octets de mémoire, mais vous avez un comportement souhaitable à peu près quand il est nécessaire. Et vous pouvez utiliser ce comportement à peu près avec d'autres sous-classes de Number.class. AbstractUnsigned étant sous-classe de Number.class lui-même fournit toutes les méthodes pratiques et constantes semblable à d'autres sous-classes de Number.class « indigènes », y compris MIN_VALUE et MAX_VALUE et beaucoup plus, par exemple, je codé méthode pratique pour les sous-classes mutables appelées makeDivisibileBy(Number n) qui effectue l'opération la plus simple de value - (value % n).

Mon premier effort était là pour montrer que même un noob, tel que je suis, peut coder. Mon premier effort quand je codais cette classe était d'obtenir l'outil pratique polyvalent pour l'utilisation constante.

scroll top