Trouvez le maximum de deux nombres. Vous ne devez pas utiliser if-else ou tout autre opérateur de comparaison. J'ai trouvé cette question sur le tableau d'affichage en ligne, donc je pensais que je devrais demander à StackOverflow
EXEMPLE Entrée: 5, 10 Sortie: 10
J'ai trouvé cette solution, quelqu'un peut-il m'aider à comprendre ces lignes de code
int getMax(int a, int b) {
int c = a - b;
int k = (c >> 31) & 0x1;
int max = a - k * c;
return max;
}
int getMax(int a, int b) {
int c = a - b;
int k = (c >> 31) & 0x1;
int max = a - k * c;
return max;
}
Disséquons ceci. Cette première ligne semble être simple: elle stocke la différence de a
et b
. Cette valeur est négative si a < b
et est non négative sinon. Il y a en fait un bogue ici - si la différence entre les nombres a
et b
est si grande qu'elle ne peut pas tenir dans un entier, cela conduira à un comportement indéfini - oups! Alors supposons que cela n'arrive pas ici.
Dans la ligne suivante, qui est
int k = (c >> 31) & 0x1;
l'idée est de vérifier si la valeur de c
est négative. Dans pratiquement tous les ordinateurs modernes, les nombres sont stockés dans un format appelé complément de deux dans lequel le bit le plus élevé du nombre est 0 si le nombre est positif et 1 si le nombre est négatif. De plus, la plupart des ints sont en 32 bits. (c >> 31)
décale le nombre de 31 bits, laissant le bit le plus élevé du nombre à la place du bit le plus bas. La prochaine étape, qui consiste à prendre ce nombre et à le remplacer par 1 (dont la représentation binaire est égale à 0 partout sauf le dernier bit), efface tous les bits les plus élevés et vous donne simplement le bit le plus bas. Étant donné que le bit le plus bas de c >> 31
est le bit le plus élevé de c
, il lit le bit le plus élevé de c
comme étant 0 ou 1. Étant donné que le bit le plus élevé est 1 iff c
est 1, cela permet de vérifier si c
est négatif (1) ou positif (0). En combinant ce raisonnement avec le précédent, k
est égal à 1 si a < b
et à 0 sinon.
La dernière étape consiste à faire ceci:
int max = a - k * c;
Si a < b
, alors k == 1
et k * c = c = a - b
, et ainsi de suite
a - k * c = a - (a - b) = a - a + b = b
Quel est le bon max, depuis a < b
. Sinon, si a >= b
, alors k == 0
et
a - k * c = a - 0 = a
Quel est également le correct max.
C'est parti: (a + b) / 2 + |a - b| / 2
Utilisez des hacks au niveau des bits
r = x ^ ((x ^ y) & -(x < y)); // max(x, y)
Si vous savez que INT_MIN <= x - y <= INT_MAX,
, vous pouvez utiliser ce qui suit, ce qui est plus rapide car (x - y)
ne doit être évalué qu'une seule fois.
r = x - ((x - y) & ((x - y) >> (sizeof(int) * CHAR_BIT - 1))); // max(x, y)
(sqrt( a*a + b*b - 2*a*b ) + a + b) / 2
Ceci est basé sur la même technique que la solution de mike.dld , mais c'est moins "évident" ici ce que je fais. Une opération "abs" donne l'impression que vous comparez le signe de quelque chose, mais je profite ici du fait que sqrt () vous retournera toujours la racine carrée positive. enracinant à nouveau, en ajoutant a + b et en divisant par 2.
Vous verrez que cela fonctionne toujours: par exemple, l'exemple utilisateur de 10 et 5 vous donne sqrt (100 + 25 - 100) = 5, puis ajoutez 10 et 5 vous donne 20 et divisez par 2 vous donne 10.
Si nous utilisons 9 et 11 comme nombres, nous aurions (sqrt (121 + 81 - 198) + 11 + 9)/2 = (sqrt (4) + 20)/2 = 22/2 = 11
La réponse la plus simple est ci-dessous.
#include <math.h>
int Max(int x, int y)
{
return (float)(x + y) / 2.0 + abs((float)(x - y) / 2);
}
int Min(int x, int y)
{
return (float)(x + y) / 2.0 - abs((float)(x - y) / 2);
}
int max(int i, int j) {
int m = ((i-j) >> 31);
return (m & j) + ((~m) & i);
}
Cette solution évite la multiplication . M sera soit 0x00000000 ou 0xffffffff
En utilisant l'idée changeante pour extraire le signe tel que posté par d'autres, voici une autre manière:
max (a, b) = new[] { a, b } [((a - b) >> 31) & 1]
Cela pousse les deux nombres dans un tableau avec le nombre maximum donné par l'élément de tableau dont l'index est le bit de signe de la différence entre les deux nombres.
Notez que:
(a - b
) peut déborder.>>
fait référence à un décalage logique à droite, le & 1
est inutile.Voici comment je pense que je ferais le travail. Ce n'est pas aussi lisible que vous le voudriez, mais quand vous commencez par "comment puis-je faire X sans utiliser la façon évidente de le faire, vous devez vous attendre à ce que . En théorie, cela donne aussi une certaine portabilité, mais il faudrait trouver un système assez inhabituel pour voir un problème.
#define BITS (CHAR_BIT * sizeof(int) - 1)
int findmax(int a, int b) {
int rets[] = {a, b};
return rets[unsigned(a-b)>>BITS];
}
Cela présente certains avantages par rapport à celui présenté dans la question. Tout d'abord, il calcule la taille correcte du décalage, au lieu d'être codé en dur pour les ints 32 bits. Deuxièmement, avec la plupart des compilateurs, nous pouvons nous attendre à ce que toute la multiplication se produise au moment de la compilation, de sorte que tout ce qui reste au moment de l'exécution est une manipulation de bits triviale (soustraction et décalage) suivie d'un chargement et d'un retour. En bref, il est presque certain que ce sera assez rapide, même sur le plus petit microcontrôleur, où la multiplication utilisée à l'origine devait se produire au moment de l'exécution. Ainsi, même si c'est probablement assez rapide sur un ordinateur de bureau, ce sera souvent assez difficile. peu plus lent sur un petit microcontrôleur.
Voici ce que font ces lignes:
c est a-b. si c est négatif, a <b.
k est le 32ème bit de c qui est le bit de signe de c (en supposant que les entiers 32 bits. Si cela est fait sur une plate-forme avec des entiers 64 bits, ce code ne fonctionnera pas). Il est décalé de 31 bits vers la droite pour supprimer les 31 bits les plus à droite, en laissant le bit de signe à l'endroit le plus à droite, puis en appuyant sur 1 pour supprimer tous les bits à gauche (qui sera rempli avec 1 si c est négatif). Donc, k sera 1 si c est négatif et 0 si c est positif.
Alors max = a - k * c. Si c est 0, cela signifie a> = b, donc max est a - 0 * c = a. Si c vaut 1, cela signifie que a <b et ensuite a - 1 * c = a - (a - b) = a - a + b = b.
Dans l'ensemble, il suffit d'utiliser le bit de signe de la différence pour éviter d'utiliser des opérations supérieures à ou inférieures aux opérations. C'est honnêtement un peu ridicule de dire que ce code n'utilise pas de comparaison. c est le résultat de la comparaison de a et b. Le code n'utilise tout simplement pas d'opérateur de comparaison. Vous pouvez faire la même chose dans de nombreux codes d'assemblage en soustrayant simplement les nombres, puis en sautant en fonction des valeurs définies dans le registre d'état.
Je devrais également ajouter que toutes ces solutions supposent que les deux nombres sont des nombres entiers. S'il s'agit de flottants, de doubles ou de quelque chose de plus compliqué (BigInts, Rational numbers, etc.), vous devez utiliser un opérateur de comparaison. Les astuces ne conviennent généralement pas à ceux-là.
int getMax(int a, int b){
return (a+b+((a-b)>>sizeof(int)*8-1|1)*(a-b))/2;
}
Permet de briser le 'max' en morceaux,
max
= ( max + max ) / 2
= ( max + (min+differenceOfMaxMin) ) / 2
= ( max + min + differenceOfMaxMin ) / 2
= ( max + min + | max - min | ) ) / 2
Donc, la fonction devrait ressembler à ceci-
getMax(a, b)
= ( a + b + absolute(a - b) ) / 2
À présent,
absolute(x)
= x [if 'x' is positive] or -x [if 'x' is negative]
= x * ( 1 [if 'x' is positive] or -1 [if 'x' is negative] )
En nombre entier positif, le premier bit (bit de signe) est - 0 ; en négatif c'est- 1 . En décalant les bits vers la droite (>>), le premier bit peut être capturé.
Pendant le décalage à droite, l’espace vide est rempli par le bit de signe. So 01110001 >> 2 = 00011100 , alors que 10110001 >> 2 = 11101100 .
En conséquence, pour un décalage de nombre de 8 bits, 7 bits produisent soit - 1 1 1 1 1 1 1 [0 ou 1] pour négatif, ou 0 0 0 0 0 0 0 [0 ou 1] pour le positif.
Maintenant, si l’opérationOUest effectuée avec 00000001 (= 1) , le nombre négatif donne- 11111111 (= -1) et positif- 00000001 (= 1) .
Alors,
absolute(x)
= x * ( 1 [if 'x' is positive] or -1 [if 'x' is negative] )
= x * ( ( x >> (numberOfBitsInInteger-1) ) | 1 )
= x * ( ( x >> ((numberOfBytesInInteger*bitsInOneByte) - 1) ) | 1 )
= x * ( ( x >> ((sizeOf(int)*8) - 1) ) | 1 )
Finalement,
getMax(a, b)
= ( a + b + absolute(a - b) ) / 2
= ( a + b + ((a-b) * ( ( (a-b) >> ((sizeOf(int)*8) - 1) ) | 1 )) ) / 2
#include<stdio.h>
main()
{
int num1,num2,diff;
printf("Enter number 1 : ");
scanf("%d",&num1);
printf("Enter number 2 : ");
scanf("%d",&num2);
diff=num1-num2;
num1=abs(diff);
num2=num1+diff;
if(num1==num2)
printf("Both number are equal\n");
else if(num2==0)
printf("Num2 > Num1\n");
else
printf("Num1 > Num2\n");
}
Le code que je fournis est pour trouver le maximum entre deux nombres, les nombres peuvent être de n'importe quel type de données (entier, flottant). Si les nombres entrés sont égaux, la fonction renvoie le nombre.
double findmax(double a, double b)
{
//find the difference of the two numbers
double diff=a-b;
double temp_diff=diff;
int int_diff=temp_diff;
/*
For the floating point numbers the difference contains decimal
values (for example 0.0009, 2.63 etc.) if the left side of '.' contains 0 then we need
to get a non-zero number on the left side of '.'
*/
while ( (!(int_diff|0)) && ((temp_diff-int_diff)||(0.0)) )
{
temp_diff = temp_diff * 10;
int_diff = temp_diff;
}
/*
shift the sign bit of variable 'int_diff' to the LSB position and find if it is
1(difference is -ve) or 0(difference is +ve) , then multiply it with the difference of
the two numbers (variable 'diff') then subtract it with the variable a.
*/
return a- (diff * ( int_diff >> (sizeof(int) * 8 - 1 ) & 1 ));
}
La description
Le bit de signe est enregistré en tant que bit le plus significatif (MSB) dans la mémoire. Si MSB est 1 et vice-versa. Pour vérifier si le bit de poids fort est égal à 1 ou à 0, nous le déplaçons sur la position du bit de poids faible et bit à bit & avec 1, si le résultat est 1, le nombre est -ve sinon non. est + ve. Ce résultat est obtenu par la déclaration:
int_diff >> (sizeof (int) * 8 - 1) & 1
Ici, pour obtenir le bit de signe du bit de plus fort poids en bit de poids faible, nous le décalons à droite sur k-1 bits (où k est le nombre de bits nécessaires pour enregistrer un nombre entier dans la mémoire, qui dépend du type de système). Ici k = sizeof (int) * 8 comme sizeof () donne le nombre d'octets nécessaires pour sauvegarder un entier pour obtenir non. de bits, nous le multiplions par 8. Après le décalage à droite, nous appliquons le bitwise & avec 1 pour obtenir le résultat.
Maintenant, après avoir obtenu le résultat (supposons-le comme r) 1 (for -ve diff) et 0 (for + ve diff), nous multiplions le résultat par la différence des deux nombres, la logique est donnée comme suit:
Maintenant, il reste deux points 1. l'utilisation de la boucle while et 2. la raison pour laquelle j'ai utilisé la variable 'int_diff' en tant qu'entier. Pour répondre correctement à ces questions, nous devons comprendre certains points:
// En C #, vous pouvez utiliser la bibliothèque mathématique pour exécuter une fonction min ou max.
en utilisant le système;
class NumberComparator {
static void Main()
{
Console.Write(" write the first number to compare: ");
double first_Number = double.Parse(Console.ReadLine());
Console.Write(" write the second number to compare: ");
double second_Number = double.Parse(Console.ReadLine());
double compare_Numbers = Math.Max(first_Number, second_Number);
Console.Write("{0} is greater",compare_Numbers);
}
}
statique int mymax (int a, int b)
{
int[] arr;
arr = new int[3];
arr[0] = b;
arr[1] = a;
arr[2] = a;
return arr[Math.Sign(a - b) + 1];
}
Si b> a then (ab) sera négatif, le signe retournera -1, en ajoutant 1, nous obtenons l'indice 0 qui est b, si b = a alors ab sera 0, +1 donnera 1 index donc peu importe si nous retournons a ou b, quand a> b alors ab sera positif et le signe retournera 1, en ajoutant 1, nous obtenons l'index 2 où a est stocké.
Voici quelques méthodes bit-twiddling pour obtenir le maximum de deux valeurs intégrales:
Méthode 1
int max1(int a, int b) {
static const size_t SIGN_BIT_SHIFT = sizeof(a) * 8 - 1;
int mask = (a - b) >> SIGN_BIT_SHIFT;
return (a & ~mask) | (b & mask);
}
Explication:
a > b
, alors a - b
est positif, le bit de signe est donc 0
et le masque est 0x00.00
. Sinon, a < b
donc a - b
est négatif, le bit de signe est 1
et après déplacement, nous obtenons un masque de 0xFF..FF
0xFF..FF
, alors ~mask
est 0x00..00
et cette valeur est 0
. Sinon, ~mask
est 0xFF..FF
et la valeur est a
0xFF..FF
, alors cette valeur est b
. Sinon, mask
est 0x00..00
et la valeur est 0
.Finalement:
a >= b
alors a - b
est positif, nous obtenons max = a | 0 = a
a < b
alors a - b
est négatif, nous obtenons max = 0 | b = b
Méthode 2
int max2(int a, int b) {
static const size_t SIGN_BIT_SHIFT = sizeof(a) * 8 - 1;
int mask = (a - b) >> SIGN_BIT_SHIFT;
return a ^ ((a ^ b) & mask);
}
Explication:
a > b
le masque est 0x00..00
, sinon le masque est 0xFF..FF
0x00..00
, alors (a ^ b) & mask
est 0x00..00
0xFF..FF
, alors (a ^ b) & mask
est a ^ b
Finalement:
a >= b
, nous obtenons a ^ 0x00..00 = a
a < b
, nous obtenons a ^ a ^ b = b