57 votes

Comment déterminer si un nombre est positif ou négatif ?

Lors d'un entretien, on m'a demandé comment déterminer si un nombre est positif ou négatif. Les règles sont que nous ne devons pas utiliser les opérateurs relationnels tels que < y > des fonctions java intégrées (comme substring , indexOf , charAt y startsWith ), pas de regex, ni d'API.

J'ai fait quelques recherches à ce sujet et le code est donné ci-dessous, mais il ne fonctionne que pour le type entier. Mais ils m'ont demandé d'écrire un code générique qui fonctionne pour les types float , double y long .

 // This might not be better way!!

 S.O.P ((( number >> 31 ) & 1) == 1 ? "- ve number " : "+ve number );

Des idées de votre côté ?

3 votes

S'il existe un moyen de convertir [quoi que ce soit] en un tableau de bits, vous pourriez examiner le bit le plus significatif pour déterminer si le nombre est positif ou négatif... Par curiosité, en quoi une telle compétence vous serait-elle utile ? Je n'ai pas encore eu de travail mais... il semble bizarre qu'ils vous enlèvent les opérateurs de base :P

147 votes

Question d'entretien stupide et artificielle

4 votes

@ItzWarty "Comment une telle compétence vous aiderait-elle ? "La curiosité vient du fait que, après 5 ans d'expérience en j2ee (j'ai passé un entretien pour un poste en java et je ne m'attendais certainement pas à cette question de leur part :( ), je me suis sentie mal à l'aise de ne pas pouvoir donner de solution avec une formation en CS.

68voto

Strilanc Points 7161

Les cas entiers sont faciles. Le cas des doubles est plus délicat, jusqu'à ce que vous vous souveniez des infinis.

Note : Si vous considérez que les constantes doubles font "partie de l'api", vous pouvez les remplacer par des expressions débordantes comme 1E308 * 2 .

int sign(int i) {
    if (i == 0) return 0;
    if (i >> 31 != 0) return -1;
    return +1;
}
int sign(long i) {
    if (i == 0) return 0;
    if (i >> 63 != 0) return -1;
    return +1;
}
int sign(double f) {
    if (f != f) throw new IllegalArgumentException("NaN");
    if (f == 0) return 0;
    f *= Double.POSITIVE_INFINITY;
    if (f == Double.POSITIVE_INFINITY) return +1;
    if (f == Double.NEGATIVE_INFINITY) return -1;

    //this should never be reached, but I've been wrong before...
    throw new IllegalArgumentException("Unfathomed double");
}

7 votes

La double solution est très astucieuse.

2 votes

D'après les commentaires précédents sur d'autres réponses, on peut dire que Double.POSITIVE_INFINITY fait partie de l'API. Je l'aime bien. Il pourrait être rendu complètement générique via un (double) cast.

0 votes

J'aime aussi la solution du double ! Cependant, les deux premières méthodes devraient retourner un booléen pour compiler.

36voto

Warty Points 4663

Ce qui suit est une approche terrible qui vous ferait virer dans n'importe quel emploi...

Cela dépend de l'obtention d'une exception Stack Overflow [ou quel que soit le nom que Java lui donne]... Et cela ne fonctionnerait que pour les nombres positifs qui ne s'écartent pas de 0 comme un fou.

Les nombres négatifs ne posent pas de problème, car ils déborderaient en positif, ce qui entraînerait une exception de débordement de pile [qui renverrait false, ou "oui, c'est négatif"].

Boolean isPositive<T>(T a)
{
  if(a == 0) return true;
  else
  {
    try
    {
      return isPositive(a-1);
    }catch(StackOverflowException e)
    {
      return false; //It went way down there and eventually went kaboom
    }
  }
}

26 votes

Celui-là m'a fait rire. :D

6 votes

Merci, mais c'est comme faire exploser une bombe et connaître le résultat.

7 votes

Et si le numéro est 1.5 ,il n'aboutira pas directement à 0 dans tous les cas, 0.5 y -0.5 vous devriez considérer cela aussi, sinon bonne idée :)

17voto

nanda Points 12764

Cela ne fonctionne que pour tout sauf [0..2].

boolean isPositive = (n % (n - 1)) * n == n;

Vous pouvez trouver une meilleure solution comme celle-ci (fonctionne sauf pour [0..1])

boolean isPositive = ((n % (n - 0.5)) * n) / 0.5 == n;

Vous pouvez obtenir une meilleure précision en remplaçant la partie 0,5 par quelque chose comme 2^m (m entier) :

boolean isPositive = ((n % (n - 0.03125)) * n) / 0.03125 == n;

1 votes

Une solution plutôt cool ! Pour le 0/1, vous pourriez le convertir en un nombre entier et s'il est égal à 0 ou 1, retourner true (ou quelque chose comme ça).

0 votes

\== n'est pas un opérateur conditionnel ?

0 votes

@billynomates : oui, c'est vrai. Cependant, en regardant les réponses, même les réponses non valides, vous n'avez pratiquement pas de solution si vous ne pouvez pas l'utiliser aussi. Après tout, ce n'est pas explicitement indiqué dans la question.

8voto

Nabb Points 2824

Vous pouvez faire quelque chose comme ça :

((long) (num * 1E308 * 1E308) >> 63) == 0 ? "+ve" : "-ve"

L'idée principale ici est d'effectuer un cast vers un long et de vérifier la valeur du bit le plus significatif. Comme un double/float compris entre -1 et 0 sera arrondi à zéro lorsqu'il est converti en un long, nous multiplions par de grands doubles afin qu'un float/double négatif soit inférieur à -1. Deux multiplications sont nécessaires en raison de l'existence de subnormaux (il n'a pas besoin d'être aussi grand).

3 votes

@nanda Le transfert d'un double trop grand vers un long donnera la plus grande valeur représentable de type long, conformément aux spécifications du langage Java (les négatifs se comportent de la même manière). De toute façon, si num tient dans un long, nous le multiplions à l'infini de toute façon (à l'exception de zéro).

0 votes

Puisque vous avez répondu rapidement pour des nombres subnormaux, je considère que j'ai accepté votre réponse.

3voto

Steven Schlansker Points 17463
// Returns 0 if positive, nonzero if negative
public long sign(long value) {
    return value & 0x8000000000000000L;
}

Appelez comme ça :

long val1 = ...;
double val2 = ...;
float val3 = ...;
int val4 = ...;

sign((long) valN);

Le transfert d'un double / float / integer vers un long devrait préserver le signe, mais pas la valeur réelle...

1 votes

Pas d'API Double.doubleToLongBits, pourquoi vous êtes AND ing avec 0x8000000000000000L , toute signification sur ce nombre.

0 votes

Merci, je pense que cette réponse est proche, je teste votre code avec le numéro 1E08, je vous tiens au courant.

2 votes

Vous retournez quelque chose et vous avez void dans la définition de la méthode.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X