web-dev-qa-db-fra.com

Est-ce techniquement un O(1) algorithme pour "Hello World"?

Serait-ce classé comme un O(1) algorithme pour "Hello, World!" ??

public class Hello1
{
   public static void Main()
   {
      DateTime TwentyYearsLater = new DateTime(2035,01,01);
      while ( DateTime.Now < TwentyYearsLater )
      { 
          System.Console.WriteLine("It's still not time to print the hello ...");
      }
      System.Console.WriteLine("Hello, World!");
   }
}

Je pense utiliser le

DateTime TwentyYearsLater = new DateTime(2035,01,01);
while ( DateTime.Now < TwentyYearsLater )
{ 
   // ... 
}

extrait de code en tant que boucle occupée à mettre en blague chaque fois que quelqu'un demande un algorithme d'une certaine complexité. Cela serait-il correct?

117
Subpar Web Dev

La notation Big O dans ce contexte est utilisée pour décrire une relation entre la taille de l’entrée d’une fonction et le nombre d’opérations à effectuer pour calculer le résultat de cette entrée.

Votre opération ne comporte aucune entrée à laquelle la sortie peut être associée. L'utilisation de la notation Big O n'a donc aucun sens. Le temps que prend l'opération est indépendant des entrées de l'opération (qui est ... aucune). Comme il n’existe aucune relation entre l’entrée et le nombre d’opérations effectuées, vous ne pouvez pas utiliser Big O pour décrire cette relation inexistante.

403
Servy

La notation Big-O signifie à peu près 'une opération sur une quantité de travail, N, combien de temps de calcul, proportionnel à N, prend l'algorithme?'. Par exemple, trier un tableau de taille N peut prendre N ^ 2, Nlog (N), etc.

Cela n’a aucune quantité de données d’entrée sur laquelle agir. Donc, ce n'est pas O(anything).

Encore pire; ce n'est pas techniquement un algorithme. Un algorithme est une méthode permettant de calculer la valeur d’une fonction mathématique - les fonctions mathématiques sont un mappage d’une entrée à une sortie. Comme cela ne prend aucune entrée et ne retourne rien, ce n'est pas une fonction, au sens mathématique. De wikipedia:

Un algorithme est une méthode efficace qui peut être exprimée dans une quantité finie d’espace et de temps et dans un langage formel bien défini pour le calcul d’une fonction. En commençant par un état initial et une entrée initiale (peut-être vide), les instructions décrivent un calcul qui, lorsqu'il est exécuté, passe par un nombre fini d'états successifs bien définis, produisant finalement une "sortie" et se terminant à un état final final.

Techniquement, il s’agit d’un système de contrôle. De Wikipédia;

Un système de contrôle est un dispositif ou un ensemble de dispositifs qui gère, commande, dirige ou régule le comportement d'autres dispositifs ou systèmes.

Pour ceux qui souhaitent obtenir une réponse plus détaillée sur la différence entre les fonctions mathématiques et les algorithmes, et les capacités plus puissantes des ordinateurs à faire des choses ayant des effets secondaires tels que la sortie de la console, l'affichage des graphiques ou le contrôle de robots, ont read of cet article sur l'hypothèse forte de Church-Turing

Résumé

La vue classique du calcul des positions de calcul en tant que transformation en boîte fermée des entrées (nombres rationnels ou chaînes finies) en sorties. Selon la vue interactive de l'informatique, le calcul est un processus interactif continu plutôt qu'une transformation basée sur la fonction d'une entrée en une sortie. Plus précisément, la communication avec le monde extérieur a lieu pendant le calcul, pas avant ni après. Cette approche change radicalement notre compréhension de ce qu'est le calcul et de sa modélisation.

L’acceptation de l’interaction en tant que nouveau paradigme est entravée par la thèse Strong Church-Turing (SCT), la conviction répandue selon laquelle les machines de Turing capturent tous les calculs, de sorte que les modèles de calcul plus expressifs que ceux-ci sont impossibles. Dans cet article, nous montrons que SCT réinterprète la thèse originale de Church-Turing (CTT) d'une manière que Turing n'avait jamais eu l'intention de faire; son équivalence communément supposée avec l'original est un mythe. Nous identifions et analysons les raisons historiques de la croyance répandue en SCT. C’est seulement en acceptant qu’il est faux que nous pourrons commencer à adopter l’interaction comme paradigme alternatif du calcul

88
Steve Cooper

Non, votre code a une complexité temporelle de O(2^|<DeltaTime>|),

Pour un codage correct de l'heure actuelle.
S'il vous plaît, laissez-moi d'abord m'excuser pour mon anglais.

Qu'est-ce que Big O et comment ça marche dans CS

La notation Big O n'est pas utilisée pour lier l'entrée d'un programme à son temps d'exécution .
La notation Big O est, en laissant de la rigueur, un moyen d’exprimer le rapport asymptotique de deux quantités .

Dans le cas de l'analyse algorithmique, ces deux quantités sont et non l'entrée (pour laquelle il faut d'abord avoir une fonction "mesure") et le temps d'exécution.
Ce sont la longueur du codage d'une instance du problème1 et une métrique d'intérêt.

Les mesures couramment utilisées sont

  1. Nombre d'étapes nécessaires pour compléter l'algorithme dans un modèle de calcul donné.
  2. L'espace requis, si un tel concept existe, par le modèle de calcul.

Implicitement, on suppose qu'un TM est le modèle, de sorte que le premier point se traduise par nombre d'applications de la transition.2 fonction, c’est-à-dire "étapes", et la seconde traduit le nombre de différentes cellules de bande écrites au moins une fois.

Est-il également souvent implicitement supposé que nous pouvons utiliser un codage apparenté polynomial à la place du codage original, par exemple une fonction qui recherche dans un tableau du début à la fin a la complexité O(n) malgré le fait qu'un codage d'instance de ce tableau devrait avoir une longueur de n*b+(n-1)b est le nombre (constant) de symboles de chaque élément. Ceci est dû au fait que b est considéré comme une constante du modèle de calcul et que l'expression ci-dessus et n sont asymptotiquement identiques.

Cela explique également pourquoi un algorithme comme le Trial Division est un algorithme exponentiel alors qu'il s'agit essentiellement d'un for(i=2; i<=sqr(N); i++) comme algorithme3.

Voir this .

Cela signifie également que la grande notation O peut utiliser autant de paramètres que nécessaire pour décrire le problème, n’est-il pas inhabituel d’avoir un paramètre k pour certains algorithmes.

Donc, ceci n'est pas à propos de "l'entrée" ou que "il n'y a pas d'entrée".

Cas d'étude maintenant

La notation Big O ne remet pas en question votre algorithme, elle suppose simplement que vous savez ce que vous faites. C'est essentiellement un outil applicable partout, même à un algorithme délibérément délicat (comme le vôtre).

Pour résoudre votre problème, vous avez utilisé la date actuelle et une date future. Elles doivent donc faire partie du problème. tout simplement: ils font partie de l'instance du problème.

Plus précisément, l'instance est:

<DeltaTime>

Où le <> Signifie n'importe quel codage de choix, non pathologique.

Voir ci-dessous pour des clarifications très importantes .

Donc, votre grand temps de complexité en O est juste O(2^|<DeltaTime>|), parce que vous faites un nombre d'itérations qui dépend de la valeur de l'heure actuelle. Il est inutile de mettre d'autres constantes numériques, car la notation asymptotique est utile car elle élimine les constantes (ainsi, par exemple, l'utilisation de O(10^|<DeltaTime>|*any_time_unit) est sans objet).

Où la partie la plus délicate est

Nous avons fait une hypothèse importante ci-dessus: que le modèle de calcul reificates5 temps, et par temps, je veux dire le temps physique (réel?). Il n'y a pas de tel concept dans le modèle de calcul standard, une MT ne sait pas le temps, nous lions le temps au nombre d'étapes car c'est ainsi que fonctionne notre réalité4.

Cependant, dans votre modèle, le temps fait partie du calcul, vous pouvez utiliser la terminologie de personnes fonctionnelles en disant que Main n'est pas pur, mais que le concept est le même.

Pour comprendre cela, il convient de noter que rien n'empêche le Framework d'utiliser un temps factice qui s'exécute deux fois, cinq fois, dix fois plus vite que le temps physique. De cette façon, votre code fonctionnera dans "la moitié", "un cinquième", "un dixième" du "temps".

Cette réflexion est importante pour choisir l’encodage de <DeltaTime>, C’est essentiellement une manière condensée d’écrire <(CurrentTime, TimeInFuture)>. Comme le temps n'existe pas au prieuré, le codage de CurrentTime pourrait très bien être le mot maintenant (ou tout autre choix) le jour précédent pourrait être codé ainsi Hier =, il en cassant l’hypothèse selon laquelle la longueur du codage augmente à mesure que le temps physique avance (et que celui de DeltaTime diminue)

Nous devons modéliser correctement le temps dans notre modèle de calcul afin de faire quelque chose d’utile.

Le seul choix sûr que nous pouvons faire est de coder des horodatages avec des longueurs croissantes (mais ne pas toujours utiliser unaire) à mesure que le temps physique avance. C’est la seule véritable propriété du temps dont nous avons besoin et celle que l’encodage doit capturer. Est-ce seulement avec ce type d'encodage que votre algorithme peut être complexe en temps?.

Votre confusion, le cas échéant, provient du fait que le mot heure dans les expressions "Quelle est sa heure complexité ? ' et 'Combien de temps temps cela prendra-t-il?' signifie des choses très très différentes

Hélas, la terminologie utilise les mêmes mots, mais vous pouvez essayer d’utiliser la "complexité des étapes" dans votre tête et de vous poser à nouveau votre question. J'espère que cela vous aidera à comprendre que la réponse est vraiment ^ _ ^


1 Cela explique également la nécessité d'une approche asymptotique, car chaque instance a une longueur différente, mais non arbitraire.
2 J'espère que j'utilise le terme anglais correct ici.
3 C'est aussi la raison pour laquelle nous trouvons souvent des termes log(log(n)) dans les mathématiques.
4 En fait, une étape doit occuper un intervalle de temps fini, mais non nul, ni non connecté.
5 Cela signifie que le mode de calcul, en tant que connaissance du temps physique, peut l’exprimer avec ses termes. Une analogie concerne le fonctionnement des génériques dans le framework .NET.

41
Yuni Mj

Bien qu'il y ait un tas d'excellentes réponses ici, laissez-moi les reformuler un peu.

La notation Big-O existe pour décrire fonctions. Appliquée à l'analyse des algorithmes, cela nous oblige à définir d'abord certaines caractéristiques de cet algorithme en termes de fonction. Le choix commun est de considérer nombre d'étapes en fonction de taille d'entrée. Comme indiqué dans d'autres réponses, proposer une telle fonction dans votre cas semble étrange, car il n'y a pas d '"entrée" clairement définie. Nous pouvons toujours essayer de le faire, cependant:

  • Nous pouvons considérer votre algorithme comme une fonction constante qui prend n'importe quelle entrée de n'importe quelle taille, l'ignore, attend un laps de temps déterminé et se termine. Dans ce cas, son temps d'exécution est f (n const) ==, et il s'agit d'un algorithme de temps O (1). C'est ce que vous vous attendiez à entendre, non? Oui, techniquement, c'est un algorithme O (1).
  • On peut considérer le TwentyYearsLater comme le paramètre d'intérêt de type "taille d'entrée". Dans ce cas, le temps d'exécution est f (n (n-x)) == où x est le "moment présent" au moment de l'appel. Vu de cette façon, il s’agit d’un algorithme à temps O (n). Attendez-vous à ce contre-argument chaque fois que vous montrez votre techniquement, algorithme O (1) à d'autres personnes.
  • Oh, mais attendez, si k =TwentyYearsLater est l'entrée, alors sa taillen est, en réalité, le nombre de bits nécessaires pour le représenter, c'est-à-dire n = log (k). La dépendance entre la taille de l'entrée n et le temps d'exécution est donc f (n 2 ^ n - x) ==. On dirait que votre algorithme vient de devenir exponentiellement lent! gh.
  • Une autre entrée du programme est en fait le flux de réponses donné par le système d'exploitation à la séquence de DateTime.Now invocations dans la boucle. Nous pouvons réellement imaginer que toute cette séquence est fournie en entrée au moment où nous exécutons le programme. Le runtime peut alors être considéré comme dépendant de la propriété de cette séquence - à savoir sa longueur jusqu'au premier élément TwentyYearsLater. Dans ce cas, le temps d'exécution est encore f (n n) == et l'algorithme est O (n).

Mais encore une fois, dans votre question, vous n’avez même pas dit que l’exécution s’intéressait à vous. Et si vous vouliez dire utiliser la mémoire? Selon la façon dont vous modélisez la situation, vous pouvez dire que l'algorithme est O (1) -mémoire ou, peut-être, O (n) -mémoire (si la mise en œuvre de DateTime.Now nécessite de garder une trace de l’ensemble de la séquence d’invocation).

Et si votre objectif était de proposer quelque chose d'absurde, pourquoi ne pas aller de l'avant et dire que vous êtes intéressé par le fait que la taille du code de l'algorithme en pixels à l'écran dépend du niveau de zoom choisi. Cela pourrait être quelque chose comme f (zoom 1/zoom) == et vous pouvez déclarer fièrement votre algorithme comme étant O (1/n) - taille du pixel!

29
KT.

Je suis en désaccord avec Servy légèrement. Il y a une entrée dans ce programme, même si ce n'est pas évident, et c'est l'heure du système. C’est peut-être un détail technique que vous n’aviez pas prévu, mais votre variable TwentyYearsFromNow ne se situe pas dans vingt ans à partir du heure du système, elle est attribuée statiquement au 1er janvier 2035.

Donc, si vous prenez ce code et l'exécutez sur une machine dont l'heure système est le 1er janvier 1970, il vous faudra 65 ans, quelle que soit la vitesse de l'ordinateur (il peut y avoir une certaine variation si son horloge est défectueuse ). Si vous prenez ce code et l'exécutez sur une machine dont l'heure système est le 2 janvier 2035, il se terminera presque instantanément.

Je dirais que votre entrée, n, est January 1st, 2035 - DateTime.Now, et c'est O (n).

Il y a aussi la question du nombre d'opérations. Certaines personnes ont remarqué que les ordinateurs les plus rapides se mettraient plus rapidement dans la boucle, entraînant plus d'opérations, mais ce n'est pas pertinent. Lorsque vous utilisez la notation big-O, nous ne tenons pas compte de la vitesse du processeur ni du nombre exact d'opérations. Si vous preniez cet algorithme et l'exécutiez sur un ordinateur, puis que vous l'exécutiez à nouveau, mais 10 fois plus longtemps sur le même ordinateur, vous vous attendriez à ce que le nombre d'opérations augmente du même facteur de 10.

En ce qui concerne:

Je pense utiliser l'extrait de code [code rédigé] comme une boucle occupée à mettre en plaisanterie chaque fois que quelqu'un demande un algorithme d'une certaine complexité. Cela serait-il correct?

Non, pas vraiment. D'autres réponses ont couvert cela, alors je voulais juste le mentionner. En règle générale, vous ne pouvez pas corréler les années d’exécution à une notation big-O. Par exemple. Il n'y a aucun moyen de dire 20 ans d'exécution = O (n ° 87) ou quoi que ce soit d'autre. Même dans l'algorithme que vous avez donné, je pouvais changer le TwentyYearsFromNow en l'année 20110, 75699436 ou 123456789 et le big-O est toujours O (n).

21
Shaz

L'analyse Big-O traite de la quantité de traitement en cause, car la quantité de données en cours de traitement augmente sans limite.

Ici, vous ne travaillez vraiment qu'avec un seul objet de taille fixe. En tant que tel, l'application de l'analyse big-O dépend fortement (principalement?) De la façon dont vous définissez vos termes.

Par exemple, vous pourriez vouloir dire impression et sortie en général, et imposer une attente si longue que toute quantité raisonnable de données sera/sera imprimée exactement dans le même laps de temps. Il faut aussi ajouter un peu plus de définitions quelque peu inhabituelles (si ce n’est carrément fausses) pour aller très loin - en particulier, l’analyse big-O est généralement définie par le nombre de les opérations fondamentales nécessaires à l'exécution d'une tâche particulière (mais notez que la complexité peut également être envisagée en termes d'utilisation de la mémoire, et pas seulement de l'utilisation du processeur/des opérations effectuées).

Le nombre d'opérations fondamentales se traduit généralement assez près par le temps, cependant, il n'est donc pas difficile de traiter les deux parties comme des synonymes. Malheureusement, nous sommes toujours bloqués sur cette autre partie: la quantité de données traitées augmente sans limite. Cela étant, aucun délai fixe que vous pouvez imposer ne fonctionnera vraiment. Pour assimiler O(1) à O (N), vous devez imposer un délai infini de sorte que toute quantité de données fixe prenne une éternité à imprimer, tout comme une quantité infinie de données .

13
Jerry Coffin

big-O par rapport à quoi?

Vous semblez avoir l'intuition que twentyYearsLater est une "entrée". Si en effet vous avez écrit votre fonction en tant que

void helloWorld(int years) {
   // ...
}

Ce serait O(N) où N = années (ou juste dire O(years)).

Je dirais que votre algorithme est O(N) par rapport au nombre que vous écrivez dans la ligne de code commençant par twentyYearsLater =. Les gens ne considèrent généralement pas les nombres dans la Le code source réel en tant qu'entrée. Ils pourraient considérer l'entrée de ligne de commande comme l'entrée ou l'entrée de signature de fonction comme l'entrée, mais très probablement pas le code source lui-même. C'est ce que vous contestez avec votre ami - est-ce le "input"? Vous configurez votre code de manière à ce qu'il apparaisse intuitivement comme une entrée, et vous pouvez certainement lui demander son temps d'exécution important par rapport au nombre N de la ligne 6 de votre programme, mais si vous utilisez un tel choix non par défaut comme entrée, vous devez vraiment être explicite à ce sujet.

Mais si vous prenez l’entrée comme quelque chose de plus habituel, comme la ligne de commande ou l’entrée de la fonction, il n’ya pas de sortie du tout et la fonction est O (1). Cela prend vingt ans, mais comme Big-O ne change pas jusqu’à un multiple constant, O(1) = O (vingt ans).

Question similaire - quelle est la durée d'exécution de:

void sortArrayOfSizeTenMillion(int[] array)

En supposant qu'il fasse ce qu'il dit et que l'entrée soit valide, et que l'algorithme exploite un tri rapide, un tri à bulles ou tout ce qui est raisonnable, c'est O (1).

10
djechlin

Cet "algorithme" est correctement décrit comme O(1) ou temps constant. Il a été avancé qu'il n'y avait pas d'entrée dans ce programme, donc il n'y avait pas de N à analyser en termes de Big Oh. Je ne suis pas d'accord sur le fait qu'il n'y a pas d'entrée. Lorsque cela est compilé dans un exécutable et appelé, l'utilisateur peut spécifier n'importe quelle entrée de longueur arbitraire. Cette longueur d'entrée est le N.

Le programme ignore simplement l’entrée (quelle que soit sa longueur), de sorte que le temps pris (ou le nombre d’instructions machine exécutées) est le même quelle que soit la longueur de l’entrée (environnement fixe = heure de début + matériel), donc O (1 ).

8
waldol1

Une chose qui me surprend n'a pas encore été mentionnée: la notation big-O est une limite supérieure!

Le problème que tout le monde a remarqué est qu’il n’existe pas de N décrivant les entrées de l’algorithme. Il n’ya donc pas d’analyse à effectuer. Cependant, ceci est facilement atténué par quelques ruses de base, telles que l’acceptation d’un int n et en imprimant "Hello World" n fois. Cela permettrait de contourner cette plainte et de revenir à la vraie question de savoir comment fonctionne cette monstruosité DateTime.

Il n'y a aucune garantie réelle que la boucle while se termine jamais. Nous aimons penser que cela doit arriver à certains temps, mais considérons que DateTime.now renvoie le date et heure du système. En fait, rien ne garantit que cela augmente de façon monotone. Il est possible que certains singes pathologiquement entraînés changent constamment la date et l'heure du système depuis le 21 octobre 2015 à 12:00 heures UTC jusqu'à ce que quelqu'un lui donne des chaussures ajustables et un hoverboard. Cette boucle peut en réalité fonctionner pendant une durée infinie!

Lorsque vous creusez dans la définition mathématique des notations big-O, ce sont des limites supérieures. Ils démontrent le pire des scénarios, aussi improbable soit-il. Le scénario * le plus défavorable étant un temps d'exécution infini, nous sommes obligés de déclarer que il n'y a pas de notation big-O pour décrire la complexité d'exécution de cet algorithme. Cela n'existe pas, tout comme 1/0 n'existe pas.

* Edit: d'après ma discussion avec KT, il n'est pas toujours correct de supposer que le scénario que nous modélisons avec la notation big-O est le pire des cas. Dans la plupart des cas, si une personne ne spécifiait pas le cas que nous utilisions, elle avait l'intention d'explorer le pire des cas. Cependant, vous pouvez effectuer une analyse de complexité big-O sur la meilleure exécution possible.

6
Cort Ammon

La complexité est utilisée pour mesurer la "puissance" de calcul en termes de temps/espace. La notation Big O est utilisée pour comparer les problèmes "calculables" ou "non calculables", ainsi que pour comparer les solutions (algorithmes) meilleures que les autres. En tant que tel, vous pouvez diviser n'importe quel algorithme en deux catégories: ceux qui peuvent être résolus en temps polynomial et ceux qui ne le peuvent pas.

Des problèmes tels que le tamis d'Erathostene sont O (n ^ exp) et peuvent donc être résolus pour de petites valeurs de n. Ils sont calculables, mais pas en temps polynomial (NP). Ainsi, lorsqu'on leur demande si un nombre donné est premier ou non, la réponse dépend de la grandeur de ce nombre. De plus, la complexité ne dépend pas du matériel, donc avoir des ordinateurs plus rapides ne change rien ...

Hello World n'est pas un algorithme et, en tant que tel, est insensé pour tenter de déterminer sa complexité - ce qui n'en est aucune. Un algorithme simple peut ressembler à quelque chose comme: à partir d’un nombre aléatoire, déterminez s’il est pair ou impair. Maintenant, est-il important que le nombre donné ait 500 chiffres? Non, car il vous suffit de vérifier si le dernier chiffre est pair ou impair. Un algorithme plus complexe consisterait à déterminer si un nombre donné se divise également par 3. Bien que certains nombres soient "faciles" à calculer, d'autres sont "difficiles" et ceci en raison de son ampleur: comparez le temps qu'il faut pour déterminer le rémanent entre un nombre à un chiffre et un autre à 500 chiffres.

Un cas plus complexe serait de décoder un texte. Vous avez apparemment un tableau aléatoire de symboles dont vous savez également qu’ils transmettent un message à ceux qui possèdent la clé de déchiffrement. Supposons que l'expéditeur utilise la clé à gauche et que votre Hello World lise: Gwkki Qieks. La solution "gros marteau, sans cerveau" produirait toutes les combinaisons pour ces lettres: de Aaaa à Zzzz, puis rechercherait un dictionnaire de mots pour identifier les mots valides et partagerait les deux lettres communes du chiffre (i, k) dans la même position. Cette fonction de transformation est ce que Big O mesure!

5
Turing

Tout le monde a bien fait remarquer que vous ne définissez pas N , mais la réponse est non, selon l'interprétation la plus raisonnable. Si N est la longueur de la chaîne que nous imprimons et “hello, world!” N'est qu'un exemple, comme nous pourrions en déduire de la description de cette comme algorithme "pour hello, world!, "Alors l'algorithme est O ( N ), car vous pourriez avoir une chaîne de sortie qui prend trente, quarante ou cinquante ans à imprimer, et vous ajoutons seulement un temps constant à cela. O (kN + c) O ( N ).

Addenda:

À ma grande surprise, quelqu'un conteste cela. Rappelez-vous les définitions de grand O et grand Θ. Supposons que nous ayons un algorithme qui attend pendant un temps constant c puis affiche un message de longueur N en temps linéaire . (C’est une généralisation de l’exemple de code original.) Disons arbitrairement que nous attendons vingt ans avant de commencer à imprimer et qu’imprimer un billion de caractères prend encore vingt ans. Soit c = 20 et k = 10¹², par exemple, mais tout nombre réel positif fera l'affaire. C'est un taux de d = c/k (dans ce cas, 2 × 10⁻¹¹) années par caractère, donc notre temps d'exécution - f ( N ) est asymptotiquement dN + c années. Chaque fois que N > k, dN = c/k N > c. Par conséquent, dN <dN + c = f ( N ) <2 dN pour tout N > k, et - f ( N ) ( N ). Q.E.D.

4
Davislor

Je pense que les gens se font avoir parce que le code ne ressemble pas à un algorithme traditionnel. Voici une traduction du code qui est plus bien formée, mais reste fidèle à l'esprit de la question d'OP.

void TrolloWorld(long currentUnixTime, long loopsPerMs){
    long laterUnixTime = 2051222400000;  //unix time of 01/01/2035, 00:00:00
    long numLoops = (laterUnixTime-currentUnixTime)*loopsPerMs;

    for (long i=0; i<numLoops; i++){
        print ("It's still not time to print the hello …");
    }
    print("Hello, World!");
}

Les entrées sont explicites alors qu’avant elles étaient implicitement données par le moment où le code a été démarré à et par la vitesse du matériel l’exécutant. Le code est déterministe et a une sortie bien définie pour des entrées données.

En raison des limitations imposées aux entrées que nous pouvons fournir, il existe une limite supérieure au nombre d'opérations qui seront exécutées. Cet algorithme est donc en fait O (1).

4
Nathan FD

La plupart des gens semblent manquer deux choses très importantes.

  1. Le programme a a une entrée. C'est la date/heure codée en dur avec laquelle l'heure du système est comparée. Les entrées sont sous le contrôle de la personne qui exécute l'algorithme, mais pas l'heure du système. La seule chose que la personne qui exécute ce programme peut contrôler est la date/heure qu’elle a codée en dur dans la comparaison.

  2. Le programme varie en fonction de l’entrée valeur, mais pas de la taille de l’entrée set, qui est ce qui concerne la notation big-O.

Par conséquent, il est indéterminé et la meilleure notation "big-O" pour ce programme serait probablement O (null), ou éventuellement O (NaN).

4
Theo Brinkman

À ce moment-là, oui

Cet algorithme a une entrée implicite, à savoir l'heure à laquelle le programme est démarré. Le temps d'exécution variera linéairement1 en fonction du moment où il est commencé. Pendant l'année 2035 et les suivantes, la boucle while se ferme immédiatement et le programme se termine après des opérations constantes2. On pourrait donc dire que le runtime est O(max(2035 - start year, 1))3. Mais comme notre année de début a une valeur minimale, l’algorithme ne prendra jamais plus de 20 ans pour être exécuté (c’est-à-dire une valeur constante).

Vous pouvez rendre votre algorithme plus conforme à votre intention en définissant DateTime TwentyYearsLater = DateTime.Now + new TimeSpan(365*20,0,0,0);4

1 Cela vaut pour le sens plus technique du temps d'exécution mesuré en nombre d'opérations, car il existe un nombre maximal d'opérations par unité de temps.
2 En supposant d'aller chercher DateTime.Now est une opération constante, ce qui est raisonnable.
3 J'abuse un peu de la grande notation O ici parce que c'est une fonction décroissante par rapport à start year, mais on pourrait facilement y remédier en l'exprimant en termes de years prior to 2035.
4 Alors, l'algorithme ne dépend plus de l'entrée implicite de l'heure de début, mais cela n'a aucune conséquence.

2
Nathan FD

Je dirais que c'est O (n). en utilisant http://www.cforcoding.com/2009/07/plain-english-explanation-of-big-o.html comme référence.

Qu'est-ce que Big O?

La notation Big O cherche à décrire la complexité relative d'un algorithme en réduisant le taux de croissance aux facteurs clés lorsque le facteur clé tend vers l'infini.

et

Le meilleur exemple de Big-O auquel je puisse penser est celui de l’arithmétique. Les opérations arithmétiques de base que nous avons apprises à l'école sont les suivantes:

une addition; soustraction; multiplication; et la division. Chacun de ceux-ci est une opération ou un problème. Une méthode pour les résoudre s'appelle un algorithme.

Pour votre exemple

étant donné l'entrée de n = 20 (avec unités années).

l'algorithme est une fonction mathématique f (). où f() est attendu pendant n années, avec des chaînes 'debug' entre les deux. Le facteur d'échelle est 1. f() peut être réduit/ou augmenté en modifiant ce facteur d'échelle.

dans ce cas, la sortie est également égale à 20 (changer d’entrée modifie la sortie de manière linéaire).

essentiellement la fonction est

f(n) = n*1 = n
    if  n = 20, then 
f(20) = 20 
1
Angel Koh