Je faisais un défi de codage et j'ai rencontré quelque chose que je ne connais pas trop. Je suis plus curieux d'apprendre ce que c'est et pourquoi il est là.
L'invite est assez simple: Given a 32-bit signed integer, reverse digits of an integer.
Example:
Input: -123
Output: -321
Example:
Input: 120
Output: 21
Assume we are dealing with an environment which could only hold integers within the 32-bit signed integer range. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.
Je suis venu avec ça.
var reverse = function(x) {
var isNegative = false;
if(x < 0){
isNegative = true;
x *= -1;
};
var reverseX = parseInt(String(x).split('').reverse((a,b) => a - b).join(''));
if(reverseX > Math.pow(2,32)){
return 0;
}
if(isNegative){
return -1 * reverseX
} else {
return reverseX;
}
};
Cependant, je suis perplexe avec certains des tests qui échouent:
Input:
1563847412
Output:
2147483651
Expected: 0
À ma compréhension, l'entier 32 bits est égal à 2 ^ 32. Quelle est sa signification dans JS et que se passe-t-il si je commence à en parler? (2^32 + 1
)
Ma deuxième question, si je peux en poser deux, est que je suis «anticipé» si la valeur de reverseX
dépasse 2 ^ 32, mais le test échoue toujours.
if(reverseX > Math.pow(2,32)){
return 0;
}
Comment puis-je renvoyer correctement 0
lorsque j'ai dépassé l'entier 32 bits?
La limite supérieure d'un entier signé n'est pas 232 - 1, mais 231 - 1, puisque le premier bit est le bit de signe.
Si vous faites cette comparaison, vous verrez que votre test donne le bon résultat.
Sachez que JavaScript utilise la virgule flottante IEEE-754 la représentation des nombres, même s'ils sont entiers. Mais la précision de la virgule flottante est plus que suffisante pour effectuer des calculs exacts sur des entiers 32 bits. Comme vous l'avez compris, vous devez effectuer le test nécessaire pour détecter le dépassement de capacité 32 bits.
Quelques notes sur votre code: il passe un argument à la méthode Array#reverse
, qui est une méthode qui ne prend pas d’argument. Voici comment je l'écrirais - voir les commentaires dans le code:
// Name argument n instead of x, as that latter is commonly used for decimal numbers
function reverse(n) {
// Array#reverse method takes no argument.
// You can use `Math.abs()` instead of changing the sign if negative.
// Conversion of string to number can be done with unary plus operator.
var reverseN = +String(Math.abs(n)).split('').reverse().join('');
// Use a number constant instead of calculating the power
if (reverseN > 0x7FFFFFFF) {
return 0;
}
// As we did not change the sign, you can do without the boolean isNegative.
// Don't multiply with -1, just use the unary minus operator.
// The ternary operator might interest you as well (you could even use it
// to combine the above return into one return statement)
return n < 0 ? -reverseN : reverseN;
}
console.log(reverse(-123));
console.log(reverse(1563847412));
Cependant, je suis perplexe avec certains des tests qui échouent:
Input:
1563847412
Output:
2147483651
Expected: 0
je crois que le nombre entier maximal de 32 bits est (2^31)
, qui est 2 147 483 647. C'est ainsi que les valeurs négatives peuvent également être stockées. (-2^31)
étant la limite de 32 bits (c'est ce que "signé" signifie). Donc, n'importe quel nombre supérieur à celui-ci, vous pouvez retourner 0 pour l'intérêt de votre programme. Si l'invite vous demandait "non signé", la plage serait de 0
à 2^32
comme vous l'aviez initialement supposé.
En ce qui concerne votre test ayant échoué, 2147483651
est 4 supérieur à 2,147,483,647
. Vous devez donc renvoyer 0. Vous devez plutôt indiquer reverseX > Math.pow(2,31) - 1
.
Quelle est sa signification dans JS et que se passe-t-il si je commence à en parler? (2 ^ 32 + 1)
Techniquement, dans JS, vous n'êtes pas limité par ce nombre. JS utilise significandevirgule flottante double précision nombres. Donc, la valeur maximale est en fait (2^53) - 1
var reverse = function(x) {
let ans;
if (parseInt(x) < 0) {
ans = parseInt(x.toString().split('').reverse().join('').toString()) * -1;
} else {
ans = parseInt(x.toString().split('').reverse().join('').toString());
}
if (ans < (Math.pow(2, 31) * -1) || ans > Math.pow(2, 31) - 1) return 0;
return ans;
};
Ça marche bien
var reverse = function(x) {
let num = Math.abs(x);
let result = 0;
let rem;
while(num>0){
rem = num % 10;
result = result * 10 + rem;
num = Math.floor(num/10);
}
if(0x7FFFFFFF < result) return 0
if(x < 0) return result * -1;
return result;
};
Voici ma solution à cette question. Je ne recommanderais pas la méthode split (). Join () car elle augmente considérablement la complexité temporelle et spatiale.
// 0(n)
var reverse = function(x) {
var reverse = 0
var isNegative = x < 0 ? -1 : 1
x = x * isNegative
// capture single digits
if (x / 10 < 1) {
return x
}
// reverse
while (x >= 1) {
var diff = parseInt(x % 10)
reverse = (reverse * 10) + diff
x = x / 10
}
// capture greater than 32bit
if (reverse > Math.pow(2,31)-1) {
return 0;
}
// capture negative
return reverse * isNegative
};