Duplicata possible:
moyen le plus rapide pour déterminer si la racine carrée d'un entier est un entier
Comment voir si un nombre est un carré parfait ?
bool IsPerfectSquare(long input)
{
// TODO
}
J'utilise C # mais c'est indépendant du langage.
Points bonus pour la clarté et la simplicité (ce n'est pas censé être du code-golf).
Edit: Cela est devenu beaucoup plus complexe que ce à quoi je m'attendais! Il s'avère que les problèmes de double précision se manifestent de deux manières. Tout d'abord, Math.Sqrt prend un double qui ne peut pas précisément tenir longtemps (merci Jon).
Deuxièmement, la précision d'un double perdra de petites valeurs (.000 ... 00001) lorsque vous aurez un énorme carré presque parfait. Par exemple, mon implémentation a échoué à ce test pour Math.Pow (10,18) +1 (le mien a rapporté vrai).
bool IsPerfectSquare(long input)
{
long closestRoot = (long) Math.Sqrt(input);
return input == closestRoot * closestRoot;
}
Cela peut éviter certains des problèmes de vérification "est la racine carrée un entier" mais peut-être pas tous. Vous devez potentiellement devenir un peu plus funk:
bool IsPerfectSquare(long input)
{
double root = Math.Sqrt(input);
long rootBits = BitConverter.DoubleToInt64Bits(root);
long lowerBound = (long) BitConverter.Int64BitsToDouble(rootBits-1);
long upperBound = (long) BitConverter.Int64BitsToDouble(rootBits+1);
for (long candidate = lowerBound; candidate <= upperBound; candidate++)
{
if (candidate * candidate == input)
{
return true;
}
}
return false;
}
Icky, et inutile pour autre chose que de très grandes valeurs, mais je pense que cela devrait fonctionner ...
bool IsPerfectSquare(long input)
{
long SquareRoot = (long) Math.Sqrt(input);
return ((SquareRoot * SquareRoot) == input);
}
Dans Common LISP, j'utilise ce qui suit:
(defun perfect-square-p (n)
(= (expt (isqrt n) 2)
n))