Question

J'ai ce code:

package math;

import java.io.IOException;
import java.util.Scanner;

public class Main
{
    public static void main(String[] args) throws IOException
    {
        System.out.println("Hi, I will beat Java's Math.sqrt(double) method");
        System.out.println("Both ways of calculation will be done");
        System.out.println("I will time how long they took to calculate");
        System.out.println("Random doubles will be generated");
        System.out.println();
        System.out.println("Please give the number of sqrt-calculation will be done");
        int calcs = new Scanner(System.in).nextInt();
        boolean output = true;
        if (calcs > 10000)
        {
            System.out.println("You're asking much calculations");
            System.out.println("Disabling output is recommend");
            System.out.println("Disable output? (y/n)");
            char a = (char) System.in.read();
            if (a == 'y')
            {
                output = false;
            }
        }
        System.out.println("Press enter to start");
        System.in.read();
        test(calcs, output);
        System.out.println();
        System.out.println("I was much faster I think");
        System.out.println("Now you can check my precision");
        System.out.println("Please give a complex double");
        double x = Double.parseDouble(new Scanner(System.in).next());
        System.out.println();
        System.out.println("Math.sqrt(" + x + ")           = " + Math.sqrt(x));
        System.out.println("SqrtCalculator.sqrt(" + x + ") = " + sqrt(x));
        System.out.println("------------------------");
        System.out.println("Now please make your conclusion");
        System.out.println("Thanks for trying");
    }

    public static void test(int calculations, boolean output)
    {
        double factor = Math.random() / 2;
        // Math
        long mathStart = System.currentTimeMillis();
        for (int i = 1; i <= calculations; i++)
        {
            double x = i * factor;
            double result = Math.sqrt(x);
            if (output)
            {
                System.out.println("Math.sqrt(" + x + ") =  " + result);
            }
        }
        long mathStop = System.currentTimeMillis();
        long mathTime = mathStop - mathStart;
        // My Method
        long myStart = System.currentTimeMillis();
        for (int i = 1; i <= calculations; i++)
        {
            double x = i * factor;
            double result = sqrt(x);
            if (output)
            {
                System.out.println("SqrtCalculater.sqrt(" + x + ") =  " + result);
            }
        }
        long myStop = System.currentTimeMillis();
        long myTime = myStop - myStart;
        System.out.println();
        if (output)
            System.out.println("---------------------------");
        System.out.println("Here are the results:");
        System.out.println("Math and SqrtCalculator did each " + calculations + " of the same sqrt-calculations");
        System.out.println();
        System.out.println("Math: " + mathTime + " milliseconds");
        System.out.println("I:    " + myTime + " milliseconds");
    }

    public final static double sqrt(double x)
    {
        double previous = 1;
        double now = 0;
        for (;;)
        {
            now = (x / previous + previous) / 2;
            if (previous == now)
            {
                return now;
            }
            previous = now;
        }
    }
}

Cette méthode sqrt est appelée " heroon ".
Si je lance mon programme et je demande 80000 calculs et désactiver la sortie, Math.sqrt () est beaucoup plus rapide que ma méthode. Si je demande 80000 CALC et activer la sortie, Ma méthode est beaucoup plus rapide.

Quelqu'un peut-il expliquer cela?

Merci

Désolé pour le mauvais anglais.

Était-ce utile?

La solution

Je ne pouvais pas reproduire vos résultats. J'ai essayé quelques fois en utilisant Eclipse Galileo et JDK 1.6.0.

Pour 80000, sortie désactivé, je suis quelque chose comme:

Math: 15 milliseconds
I:    32 milliseconds

petit temps, il serait préférable d'utiliser System.nanoTime() ou plusieurs interactions.

Pour 80000, sortie activée:

Math: 3609 milliseconds
I:    4906 milliseconds

Alors sans doute le problème est la manière dont la sortie est gérée (défilement, mise en mémoire tampon, ...)

Autres conseils

La méthode Math.sqrt remet à StrictMath.sqrt, qui se fait dans le matériel ou le code natif. (Regardez la source du JDK - vous verrez que c'est une méthode native.) Ceci est certainement plus rapide que tout ce que vous écrivez. Il pourrait même utiliser le même algorithme que vous codé. C'est bien connu. Votre méthode est tout simplement la méthode de Newton pour le calcul des racines carrées. Il est connu depuis Babylone ; Newton simplement rederived à l'aide de calcul. la convergence du second degré est bon.

Tout ce que vous avez fait, il est peu probable que vous avez découvert quelque chose de nouveau ou digne de mention. On dirait que quelque chose ayant à voir avec IO biaise artificiellement les résultats.

Vous êtes probablement écrasante le temps de calcul réel avec le temps de sortie, et en cours d'exécution dans un coup de chance de la mise en mémoire tampon. Un profileur vous montrer ce qui consomme réellement le temps.

Coup de coeur pour essayer d'améliorer sur une mise en œuvre existante; même si vous ne parvenez pas, vous pouvez en apprendre beaucoup sur les algorithmes dans le processus. Bien sûr, vous devez tester votre solution en utilisant ce type de micro-référence. Malheureusement, il y a de nombreux pièges. En particulier, ne pas mélanger le code non pertinent, les tests et la production par exemple, avec votre calcul; ne réchauffer la machine virtuelle Java au début de votre test. Il y a plus dans cette sur benchmarking. En outre, lorsque l'on compare les valeurs à virgule flottante, tenez compte Directives pour comparer les nombres à virgule flottante .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top