Si vous êtes à la réflexion sur l'utilisation de la virgule flottante pour les aider avec entier arithmétique, vous devez être prudent.
J'ai l'habitude d'essayer d'éviter FP calculs à chaque fois que possible.
Les opérations à virgule flottante ne sont pas exactes. Vous ne pouvez jamais savoir avec certitude ce que sera (int)(Math.log(65536)/Math.log(2))
évaluer. Par exemple, Math.ceil(Math.log(1<<29) / Math.log(2))
30 sur mon PC où mathématiquement cela devrait être exactement 29. Je n'ai pas trouver une valeur de x, où (int)(Math.log(x)/Math.log(2))
d'échec (juste parce qu'il y a seulement 32 "dangereux" valeurs), mais cela ne signifie pas que cela fonctionnera de la même manière sur n'importe quel PC.
L'habitude astuce ici est d'utiliser "epsilon" lors de l'arrondissement. Comme (int)(Math.log(x)/Math.log(2)+1e-10)
ne doit jamais échouer. Le choix de cette "epsilon" n'est pas une tâche triviale.
Plus de démonstration, à l'aide d'une tâche plus générale - essayer de mettre en oeuvre int log(int x, int base)
:
Le code de test:
static int pow(int base, int power) {
int result = 1;
for (int i = 0; i < power; i++)
result *= base;
return result;
}
private static void test(int base, int pow) {
int x = pow(base, pow);
if (pow != log(x, base))
System.out.println(String.format("error at %d^%d", base, pow));
if(pow!=0 && (pow-1) != log(x-1, base))
System.out.println(String.format("error at %d^%d-1", base, pow));
}
public static void main(String[] args) {
for (int base = 2; base < 500; base++) {
int maxPow = (int) (Math.log(Integer.MAX_VALUE) / Math.log(base));
for (int pow = 0; pow <= maxPow; pow++) {
test(base, pow);
}
}
}
Si nous utilisons la plus directe de mise en œuvre de logarithme,
static int log(int x, int base)
{
return (int) (Math.log(x) / Math.log(base));
}
cette affiche:
error at 3^5
error at 3^10
error at 3^13
error at 3^15
error at 3^17
error at 9^5
error at 10^3
error at 10^6
error at 10^9
error at 11^7
error at 12^7
...
Pour complètement se débarrasser des erreurs, j'ai dû ajouter epsilon qui est entre 1e-11 1e-14.
Pourriez-vous lui avez dit cela avant de tester?
J'ai vraiment pas pu.