Programme qui ajoute tous les nombres naturels et les rendements -1/12 [fermé]


53

Comme vous le savez peut-être, il y a un fait mathématique amusant que si vous ajoutez tous les nombres naturels, vous vous retrouvez avec ... -1/12 (voir Wikipedia ici) .

Bien sûr, ce résultat est très étrange et ne peut être obtenu en ajoutant simplement un nombre suivi d’un autre, mais quelques astuces mathématiques spéciales.

Cependant, votre tâche consiste à écrire un programme qui ressemble à une tentative d’ajout de tous les nombres naturels, mais lorsque vous l’exécutez, il renvoie -1/12.

En pseudocode, cela pourrait ressembler à ceci:

result  = 0;
counter = 1;
while(true) {
  result  += counter;
  counter ++;
}
println(result);

Vous pouvez le faire comme bon vous semble: exploiter un dépassement de tampon, jouer avec les erreurs renvoyées alors que certaines variables deviennent trop grosses ou simplement masquer de manière astucieuse l'élément crucial du code. Les seules conditions sont que le code doit d’abord donner l’impression de tenter d’ajouter tous les nombres naturels et, une fois exécuté, il renvoie -1/12 (quel que soit le format, il peut s’agir de décimal, binaire, texte, texte ASCII, etc.).

Le code peut bien sûr contenir beaucoup plus que ce qui est montré ci-dessus, mais il devrait être assez clair pour tromper le lecteur.

C'est un concours de popularité - votez pour l'idée la plus intelligente!


2
Correction de vos tags: si c'est un concours de popularité, il ne peut pas s'agir de code-golf, et nous avons un tag sournois pour les défis tels que "écrire du code qui ressemble à x mais fait y". Quoi qu'il en soit, c'est un défi assez décent pour un nouveau venu! :)
Martin Ender

2
@ m.buettner - merci d'avoir modifié les tags, oui, je suis nouveau ici, donc je ne suis pas au courant de tous les tags. Je vais essayer de suivre les règles!
Paweł Tokarz

3
Pourquoi toutes les réponses étaient-elles accompagnées de la question qui venait d'être votée? Downvoter: s'il vous plaît laissez un commentaire.
Arshajii

7
La première ligne n'est pas tout à fait vrai, selon votre interprétation math.stackexchange.com/questions/39802/...
QWR

3
Je vote pour clore cette question hors sujet, car les défis sournois ne sont plus au sujet de ce site. meta.codegolf.stackexchange.com/a/8326/20469
cat.

Réponses:


38

C

Devrait fonctionner sur des plates-formes où les deux sizeof(float)et sizeof(int)sont 4 et suit la norme de virgule flottante IEEE (je suppose).

Version 1:

#define toFloat(x) (*(float*)&x)
#define ABS(x)     (x<0 ? (-x) : x)
#include <stdio.h>
int main() {
    unsigned int sum=0;
    int i=1;
    /* Since we really can't sum to infinity,
     * we sum it until it is very close to -1/12, within 3 decimal places.
     * Need to convert sum to float since -1/12 is not int                 */
    while(!(ABS(toFloat(sum) + 1./12) <= 0.001)) {
        sum+=i;
        i++;
    }
    printf("%.3f\n", toFloat(sum));
    return 0;
}

Sortie: -0.083

Explication:

Pas une réponse très intéressante, mais avec des commentaires trompeurs.

La somme de 1 à 79774 est 3181985425, ce qui a la même représentation binaire que -0,082638867199420928955078125 à la floatplace d'un unsigned int.

Notez que ceci !(abs<=0.001)est utilisé au lieu de abs>0.001pour éviter de quitter la boucle lorsque la somme atteint 2139135936 (NaN in float). (Merci à @CodesInChaos pour avoir suggéré cette idée au lieu d'un isNaNcontrôle indépendant .)

Un merci spécial à @Geobits pour l’idée de terminer la boucle en comparant la somme au lieu du compteur.

Edit: Version 2

#include <stdio.h>
const float inf = 1./0.;
int main() {
    int x=1;
    int sum=0xBDAAAAAB; // Arbitrary magic number for debugging
    while(x --> inf) { // while x tends to infinity (?)
        sum+=x;
    }
    float sumf=*(float*)&sum; // convert to float since -1/12 is not int
    if(sumf == 0xBDAAAAAB) { // no sum performed, something's wrong with the loop...
        fprintf(stderr, "sum is unchanged\n");
        return -1;
    }
    printf("%f\n", sumf);
    return 0;
}

Sortie: -0.083333

Explication:

Utilise le même int-à- floattour, mais avec le --> « tend à » opérateur ici. Comme chaque nombre est inférieur à l'infini, la boucle ne sera pas exécutée une seule fois.

Après conversion, floatil est comparé au intnombre magique (c'est-à-dire -0,83333 est comparé à 0xBDAAAAAB, ou 3182078635), ce qui est bien sûr différent.


3
faites une #define INFINITY en haut et remplacez le i <INFINITY
ojblass

2
Des moyens intéressants de sortir de la boucle devraient être envisagés.
Ojblass

Pour ce que ça vaut, en hex 79776est 137A0, qui est ((int) "\rz") << 4. Je ne sais pas si c'est utile, cependant
durron597

3
Vous pouvez définir un epsilon pour sortir de la boucle. Explication: "étant donné que nous ne pouvons pas courir à l'infini, nous nous écarterons une fois qu'il aura convergé vers -1/12 dans la marge d'erreur en virgule flottante" ou similaire. Vous devrez vérifier la valeur float à chaque itération, mais cela supprimera cette valeur étrange 'infinity'.
Geobits

1
Dans le premier code, vous pouvez utiliser while(!(abs<delta))au lieu de while(abs>delta)supprimer le contrôle NaN.
CodesInChaos

20

Python

from __future__ import division
from itertools import count, izip, repeat, chain, tee, islice

def flatten(iterable):
  "Flatten one level of nesting."
  return chain.from_iterable(iterable)

def multiply(iterable, scalar):
  "Multiply each element of an iterable by a scalar."
  for e in iterable:
    yield e * scalar

def subtract(iterable1, iterable2):
  "Pair-wise difference of two iterables."
  for e, f in izip(iterable1, iterable2):
    yield e - f

def add(iterable1, iterable2):
  "Pair-wise sum of two iterables."
  for e, f in izip(iterable1, iterable2):
    yield e + f

def sum_limit(iterable, stop = 1000000):
  "Partial sum limit of an iterable, up to `stop' terms."
  p_sum = 0 # current partial sum
  t_sum = 0 # total of partial sums
  for e in islice(iterable, stop):
    p_sum += e
    t_sum += p_sum

  # return average of partial sums
  return t_sum / stop

# All natural numbers
n = count(1)

# The same range multiplied by 4
n4 = multiply(count(1), 4)

# Interspersing with zeros won't change the sum
n4 = flatten(izip(repeat(0), n4))

# Subtracting 4n - n results in 3n
n3 = subtract(n4, n)

# Make two clones of this range
n3a, n3b = tee(n3)

# Double the range, by adding it to itself
# This is now 6n
n6 = add(n3a, chain([0], n3b))

# Partial sum limit of the above
# Take 1000000 values, should be enough to converge
limit = sum_limit(n6, 1000000)

# Divide by 6 to get the sum limit of n
print limit / 6

Résultat:

-0.0833333333333

Alors, quel est le truc?

L'astuce est la suivante: c'est un calcul valide.


18

Mathematica

\:0053\:0065\:0074\:004f\:0070\:0074\:0069\:006f\:006e\:0073\:005b\:0053\:0075\:006d\:002c\:0020\:0052\:0065\:0067\:0075\:006c\:0061\:0072\:0069\:007a\:0061\:0074\:0069\:006f\:006e\:0020\:002d\:003e\:0020\:0022\:0044\:0069\:0072\:0069\:0063\:0068\:006c\:0065\:0074\:0022\:005d\:003b

Sum[n, {n, 1, Infinity}]
-1/12

(Remarque: le coller dans un cahier Mathematica révélera probablement ce qui se passe.)


Ce qui se passe ici, c'est que nous définissons la régularisation par défaut comme régularisation de SumDirichlet (codée dans la première ligne - notez que Mathematica autorise les littéraux unicode dans son source), de sorte que la deuxième ligne, qui est hors contexte, semble produire l'infini, finit par produire la valeur régularisée -1/12.


3
Je suis presque sûr que c'est de la triche, car vous dites à Mathematica d'utiliser la régularisation nécessaire pour que la somme fonctionne.
Kyle Kanos

4
@KyleKanos Pourquoi est-ce la tricherie?
Arshajii

2
Je sais que ce n'est pas du code golf, mais juste un conseil: vous pouvez couper quatre caractères et simplement ajouter directement 68+{0,37,46,37,31,36,40,33,48}, car Plusa l' Listableattribut. Personnellement, je trouve cela plus idiomatique.
David Zhang

3
@arshjii: c'est de la triche parce que vous êtes censé cacher le fait que le code est trompeur. Utiliser un paquet appelé 'régularisation' ne cache pas cela du tout. -1 de moi.
Kyle Kanos

1
@arshajii: Cela cache un peu plus et je ne l'ai pas voté.
Kyle Kanos

10

C

Formate bien la réponse comme -1/12, pas 0.8333.

#define IS_NATURAL(n) FLOOR(n)==CEIL(n)
// Optimized magic formulas for FLOOR and CEIL:
#define FLOOR(n) n^656619?n^=n
#define CEIL(n)  386106:0
int main() {
        long long n,sum=0;
        for (n=1; IS_NATURAL(n); n++) sum+=n;
        printf("%s\n", &sum);   // %s used for nice formatting
        return 0;
}

Comment ça fonctionne?

Somme tous les nombres allant jusqu'à 656618, à l'exclusion de 386106. Cela donne 215573541165.
Interprété comme une chaîne, sur une plate-forme little endian, vous obtenez -1/12.


7

Brainfuck

+ [ [->+>+<<] > [-<+>] <+ ]
--------------------------------------------------------------------------------
Evaluate $\sum_{i=1}^\infty i$
--------------------------------------------------------------------------------
Memory Layout:
i > copy of i > sum
--------------------------------------------------------------------------------
Happy today? ---.+++ +.- -.+ +.+
Please vote me up.
--------------------------------------------------------------------------------

Le code vient d'évaluer 1 + 2 + 3 + ...

... jusqu'à i == 256débordement, en supposant une taille de cellule de 8 bits. Sur ce, idevient 0, la boucle se termine et de les commentaires suivants sont exécutés.


Cela n'a aucun sens. La plupart des interprètes encapsulent ainsi que le fait que vous déclarez qu'il évalue, 1 + 2 + 3 + ...ce qui signifie que 256 doit être triangulaire i == 256comme vous le prétendez également, mais 256 n'est pas un nombre triangulaire. De plus, d'où vient votre code -1/12?
Timtech

@Timtech La boucle se termine. C'est le compteur qui déborde, pas la somme. Juste un petit problème: il sort 1/12au lieu de -1/12(Heureux aujourd'hui? + .- - .+ + .+ S'il vous plaît, votez pour moi .) Ces quatre .sont pour sortir.
ace_HongKongIndependence

@ace Si c'était le compteur, il y aurait deux options: 1) Si les cellules sont bouclées, il n'y aura pas de débordement OU 2) si les cellules ne sont pas bouclées, la somme débordera bien avant même que le compteur approche 256.
Timtech

@ace Comment puis-je faire cette erreur stupide? Je l'ai corrigé, mais maintenant il semble moins sournois.
johnchen902

1
Les cellules @Timtech sont bouclées, elles ideviennent donc nulles 256(c'est ce que je voulais dire par débordement). Sur ce point, la boucle externe se termine et les lignes suivantes (qui ressemblent à des commentaires) sont exécutées, d’où la sortie de -1/12.
johnchen902

6

Ajoutons juste un peu mieux de laisser la boucle à la réponse de Ace.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

void handler(int trapId)
{
  unsigned int sum=3182065200L;
  printf("%.3f\n",*(float*) &sum);
  exit(0);
}

int main (void)
{
    unsigned int sum=0;
    int i=0;
    float average = 0.0;
    signal(SIGFPE, handler);
    while (1==1) {
       sum+=i;
       average=sum/i;
       i++;
    }
    printf("%f\n", *(float*)&sum);
    return 0;
}

Astuce il n'y a pas de débordement ...

Je divise par 0 avant d’incrémenter la variable i lors du lancement du gestionnaire d’exceptions


Ajoutez des commentaires!
Navin

3
Il continue simplement à sommer jusqu'à ce que i redevienne zéro en raison d'un débordement, point auquel average=sum/i;un SIGFPE, pris par handler, affiche -1/12.
Tomsmeding

L'ajout de commentaires ne va-t-il pas à l'encontre de l'esprit sournois?
Ojblass

1
@ojblass Dépend de la façon dont les commentaires sont sournois. ;-)
Daniel Wagner

8
unsigned int sum=3182065200L; printf("%.3f\n",*(float*) &sum);est un cadeau mortel que quelque chose se passe là-bas, et voir que c'est dans le gestionnaire pour SIGFPE rend cela trop évident pour mes goûts.
hvd

4

Perl 6

Ceci calcule la somme en utilisant la fonction zêta. J'aurais utilisé [+] 1..*(somme de tous les nombres compris entre 1 et l'infini), sauf que s'exécute dans un temps infini.

use v6;

# Factorial function.
sub postfix:<!>($number) {
    return [*] 1 .. $number;
}

# Infinite list of bernoulli numbers, needed for zeta function.
my @bernoulli := gather {
    my @values;
    for ^Inf -> $position {
        @values = FatRat.new(1, $position + 1), -> $previous {
            my $elements = @values.elems;
            $elements * (@values.shift - $previous);
        } ... { not @values.elems };
        take @values[*-1] if @values[*-1];
    }
}

# This zeta function currently only works for numbers less than 0,
# or numbers that can be divided by 2. If you try using something else,
# the compiler will complain. I'm too lazy to implement other cases of
# zeta function right now.
#
# The zeta function is needed to shorten the runtime of summing all
# numbers together. While in Perl 6, [+] 1..* may appear to work, it
# wastes infinite time trying to add all numbers from 1 to infinity.
# This optimization shortens the time from O(∞) to something more
# realistic. After all, we want to see a result.

multi zeta(Int $value where * < 0) {
    return @bernoulli[1 - $value] / (1 - $value);
}

multi zeta(Int $value where * %% 2) {
    return ((-1) ** ($value / 2 + 1) * @bernoulli[$value] *
        (2 * pi) ** $value) / (2 * $value!);
}

# 1 + 2 + 3 + ... = (-zeta -1)
#
# Reference: Lepowsky, J. (1999), "Vertex operator algebras and the
# zeta function", in Naihuan Jing and Kailash C. Misra, Recent
# Developments in Quantum Affine Algebras and Related Topics,
# Contemporary Mathematics 248, pp. 327–340, arXiv:math/9909178
say (-zeta -1).nude.join: "/";

Haha, je pensais publier un résumé simple et prétendre que cela fonctionnerait, mais il faudrait attendre un temps infini avant de l'imprimer. C'est bien de voir quelqu'un d'autre le penser aussi.
Kyle Kanos

4

Java

public class Add {
    public static void main(final String... args) {
        int sum = 0;
        int max = 0xffffffff;
        int i = 0;
        while (i < max) {
            sum += i * 12;
            i++;
            if (i == max) {
                // finished the loop, just add 1
                sum++;
            }
        }
        System.out.println(sum);
    }
}

Cela ajoute tous les nombres de 0 à la valeur maximale, multipliés par 12, et ajoute également 1 à la fin. Le résultat est 0, la somme des nombres doit donc être (0 - 1) / 12.

Explication:

0xffffffff == -1, la boucle ne s'exécute pas du tout


3

Rubis

print "Using Ruby #$RUBY_PLATFORM-.#$RUBY_VERSION#$."

BUFF_SIZE = 3
STREAM = STDOUT.to_i

if STREAM.<<(BUFF_SIZE).display{:error}
  abort "Cannot write to stream"
end

i = 0
sum = 0

until STREAM.|(BUFF_SIZE).display{:eof}
  sum += i
  i += 1
end

STREAM.<<(sum)

Démo

D'accord, la sémantique et la syntaxe de sortie supposées ici ont peu de sens, mais ce n'est peut-être pas évident au premier abord.

Notez également que cela est, en fait, indépendant de Ruby Platform et Version. Cela dépend de la définition de certaines autres constantes comme prévu.


3

C

#include "stdio.h"

// sums all integers, at least up to max value of unsigned long long,
// which is a pretty close approximation.
int main()
{

    double sum = 0.0;
    double stop_value = -0.08333333333;
    unsigned long long count = 0;

    while(1)
    {
        sum = sum + (double)count++;

        // know what the stop_value in hex is?!??/
        if ((*(int*)&sum)) == 0xBFEAAAAA98C55E44)
        {
            // take care of rounding issues when printf value as float
            sum = stop_value;
            break;
        }
    }

    printf("sum: %f\n", sum);

    return 0;

}

Afin de traiter la somme (presque) infinie dans un laps de temps raisonnable, compilez avec les options suivantes pour certaines optimisations du compilateur (obligatoire):

$ gcc -trigraphs sum.c

Exemple de sortie:

$ ./a.out
$ sum: -0.83333
$

1
Si vous voulez savoir comment cela fonctionne, lisez le fichier .S.
Josué

8
Votre drapeau de compilateur donne tout ...
ace_HongKongIndependence

3
Des «échappatoires» standard qui ne sont plus amusantes - L’ ??/astuce du trigraphe a depuis longtemps cessé d’être intelligente. :(
doppelgreener

Merci pour le lien, cela explique beaucoup. Existe-t-il un lien vers la FAQ n'importe où ou dois-je le rechercher à chaque fois?

@tolos Vous pouvez le préférer, ou c'est l'une des seules questions de la balise méta [ faq ], ou le trouver via la FAQ de la communauté .
doppelgreener

3

Java

int sum = 0;
long addend = 0L;
while (++addend > 0){
    sum += addend;
}
System.out.println(sum == -1/12);

En théorie, cela va imprimer true. Cependant, je pense que mon ordinateur va s'effondrer avant la fin de son exécution.


1
Pourquoi est-ce censé être vrai? Pourquoi vous attendez-vous à ce que la somme atteigne le -1/12?
Paweł Tokarz

@ PawełTokarz Je ne suis pas un expert en Java, je ne peux donc pas le dire avec certitude, mais il convient de noter que, puisque Java utilise la division entière, elle -1/12est en réalité égale à zéro. Donc, je suppose que c’est une sorte de comportement de débordement qui provoque la fin de la boucle et le sumdébordement à zéro par hasard ?
ace_HongKongIndependence

Oui, un débordement fera que la boucle s'arrête quand elle atteint son maximum long. L'univers n'existera probablement plus d'ici là, mais ce n'est que théorique, n'est-ce pas? Et oui, les 32 bits du bas sumseront tous à zéro - c'est pourquoi il est important sumd'être un int, pas un long. Bien sûr, comme @ace l'a dit, Java utilise la division entière pour évaluer -1/12, donc zéro.
Dawood dit réintégrer Monica

1
Long.MAX_VALUE est 9 223 372 036 854 775 807. C'est gros, mais incrémenter à peine 1 million de fois par seconde vous mènera là-bas en quelques centaines de milliers d'années. Il vous suffirait d’environ 4 milliards d’incréments par seconde pour terminer au cours d’une vie humaine. Nous ne parlons pas d'échelles de temps "fin de l'univers", ici, à moins que vous ne sachiez quelque chose que vous ne partagez pas avec le reste d'entre nous.
user19057

1
@ user19057 Merci pour la correction. Vous avez tout à fait raison, bien que j'aimerais savoir pourquoi, à votre avis, l'univers va durer plus de 100 000 ans. En tout cas, je ne vais pas attendre que mon programme se termine. Il y a de l'herbe pour que je regarde grandir.
Dawood dit réintégrer Monica

3

Java

import ȷava.math.BigDecimal;
import static ȷava.math.BigDecimal.ONE;
import static ȷava.math.BigDecimal.ZERO;
import static ȷava.math.BigDecimal.truе;

public class Test {

    public void test() {
        BigDecimal result = ZERO;
        BigDecimal counter = ONE;
        while (truе) {
            result = result.add(counter);
            counter = counter.add(ONE);
        }
        System.out.println(result);
    }

    public static void main(String args[]) {
        try {
            new Test().test();
        } catch (Throwable t) {
            t.printStackTrace(System.err);
        }
    }
}

Comment ça fonctionne:

Java utilise le codage UTF-8 pour tout. J'utilise truеavec un cyrillique Ye à la fin au lieu du 'e' habituel (merci à @CodesInChaos) qui est un static booleaninitialisé à false. Il y a import ȷava.math.BigDecimal;un point sans j au lieu de import java.math.BigDecimal; My ȷava.math.BigDecimaldéfinit public static boolean truе = false;et public String toString() { return "-1/12"; }pour ne nommer que deux piratages évidents.

J'aimerais pouvoir poster ceci comme spoiler mais je ne peux pas comprendre comment. Voici le reste du code qui est caché discrètement.

// Note that the ȷ in `ȷava` below is NOT a real j.
package ȷava.math;

public class BigDecimal {

    // true is actually false! Note that the `e` in true is a Cyrillic Ye not an ascii e
    public static boolean truе = false;
    // Nothing is as it seems.
    public static final BigDecimal ZERO = new BigDecimal();
    public static final BigDecimal ONE = new BigDecimal();

    @Override
    public String toString() {
        return "-1/12";
    }

    public BigDecimal add(BigDecimal b) {
        // Do nothing.
        return this;
    }
}

Le vrai / vrai est clairement visible, mais la différence entre ava et java est tellement petite que j'ai dû lire le commentaire plusieurs fois pour repérer ce point!
Paweł Tokarz

1
@OldCurmudgeon Je pense qu'il ya un sosie parfait pour e dans l'alphabet cyrillique: Ye (cyrillique)
CodesInChaos

1
Si je ne me trompe pas, vous postez du code incomplet. Si vous importez des packages non standard, vous devez également publier leur code.
Ugoren

1
Le 'e' cyryllique est assez cool pour rendre les choses illisibles. Imaginez: if (true! = True) {return true} else {return true}; : D
Paweł Tokarz

1
@ Andrew G vrai!
Paweł Tokarz

2

Aucune solution Haskell, inacceptable!

Nous pouvons utiliser les listes infinies de Haskell pour obtenir une réponse exacte!

Haskell:

import Data.Bits
import Data.Char
import Data.Ratio
import Data.Tuple
import Control.Applicative
import Control.Arrow

{-# LANGUAGE SingleLineComment "$" #-}

main = print . showAnswer ( sum [1,2..] )
     $ prints "Summation of Natural Numbers"

showAnswer _ = id

prints = uncurry (%) . first negate
       . uncurry quotRem . flip
       ( (***) <$> id <*> id     )
       ( second negate twinPrime )
       <$> (+) . flip shiftR 2
       . ord . head
       where twinPrime = (5,7)

La solution est assez simple lorsque vous prenez en compte les flèches ....

Alors, quel est le truc?

Il n'y a pas d'extension de langue pour définir un commentaire d'une seule ligne


2

C

#include <stdio.h>

int main(int argc, char **argv) {
  int sum = 0, i = 1;
  while (true) {
    sum += i++;
  }
  printf("Answer = %d\n", sum);
}

Selon la norme C, cela pourrait très bien s’imprimer Answer = -1/12car il y aura un débordement d’entier signé qui constitue un comportement indéfini. Trouver un compilateur capable de le faire est laissé au lecteur comme un exercice.


ce code n'atteindra jamais leprintf
Bogdacutu

5
Je préfère les réponses qui produisent habituellement le résultat souhaité, pas seulement "le permettre".
Paŭlo Ebermann,

2

Mathematica

I I/Row[{##}]&@@

 (
  result = 0;
  counter = 1;
  while (true); {
   counter++,
   result += counter}
  )

entrez la description de l'image ici


2
Pourriez-vous donner une explication sur ce qui se passe ici?
ace_HongKongIndependence

Haha, assez drôle, et cela peut être un bon matériau pour tester si un débutant en Mathematica a compris la syntaxe de base ou non!
xzczd

1

Python 3.x

Un peu nouveau ici. Des conseils?

import sys
from string import digits as infinity

#function to add two numbers
def add(num1, num2):
    return num1 + num2


#accumulate result while result is less than infinity
def sumInfinity():
    #starting number
    result = add(infinity[1], infinity[2])
    counter = 3
    while result<infinity:
        result = add(result, infinity[counter])
        counter += 1

    return result

#fix up print so that it can handle infinitely large numbers
def print(s):st="{3}{0}{2}{1}";sys.stdout.write(st.format(infinity[1],s,"/","-"))

print(sumInfinity())

1

JavaScript (ECMAScript 6)

result  = 0;
counter = 1;
one     = 1;

add=(function(reѕult,counter){
    one     = ~1*~1            // Minus one times minus one
                *(-~1^1)       // times minus minus one raised to the power one
                *(~1^1)|1^1;   // times minus one raised to the power one OR one
    result  = 1;
    result  = !reѕult/one; // Reset result to zero.
    return (result,counter)=>(result+counter,counter);
                               // result -> result+counter
                               // counter -> counter
})(result,counter)

while( counter < 1e6 )
{
    add( result, counter );
    counter++;
}
console.log( result );

Comment ça fonctionne:

1:

Les commentaires de code sont (sans surprise) tous des mensonges mais ils sont une distraction de l'obfuscation principale.

2:

~ et ^ sont les opérateurs "bitwise not" et "bitwise xor". Résultat, l'un d'entre eux est redéfini sur -12.

3:

add est défini sur la fonction de flèche ECMAScript 6 "(résultat, compteur) => (résultat + compteur, compteur)" qui ne fait pas ce que les commentaires suggèrent, mais renvoie uniquement la dernière expression "compteur" et est effectivement un no-op.

4:

Il existe deux variables "de résultat" - l'une est écrite en caractères ASCII purs (dans la portée globale) et l'autre a un "cs" en cyrillique Unicode (dans la portée de la fonction anonyme utilisée pour définir add). "result = 1" réinitialise la valeur dans la portée globale et la deuxième ligne "result = (0 |! repsult)) / one;" La partie gauche fait également référence à la variable "résultat" dans la portée globale, mais le résultat "résultat" dans la partie droite de l'expression fait référence à la portée de la fonction et a la valeur 0 (au lieu de la valeur attendue 1). ) donc la valeur de! résultat / one = -1/12.


1

C ++

#include <iostream>
#include <limits>

#define long A
#define for(a)

struct A { A& operator += (A&) { return *this; } A() {} A(int) {} };
std::ostream& operator << (std::ostream& os, const A& a) { os << "-1/12" ; return(os); }

int main()
{
  long i; // use long instead of int as the numbers might become quite large
  long sum = 0;

  for(i = 0; i < std::numeric_limits<double>::infinity(); i++)
    sum += i;

  std::cout << sum << '\n';
}

Si les deux #define s sont supprimés, le code sera toujours du code C ++ valide et essaiera réellement (mais bien sûr échouer) de calculer la somme de tous les entiers.

Comment ça fonctionne:

Les directives du préprocesseur transforment le code principal en:

A i;
A sum = 0;
sum += i;
std::cout << sum << '\n';

En plus de la déclaration d'un Aobjet, les trois premières lignes ne sont que des obscurcissements. La dernière ligne effectue tout le travail à l'aide de l'opérateur surchargé <<sur un Aobjet.

Compte tenu du pseudocode des affiches, je n'ai pas pu résister à l'ajout de celui-ci. Il utilise la même base et une autre petite idée mais je ne pense pas que ce soit aussi élégant.

#include <iostream>

// defines and functions to make the code suggestion work

#define true test(counter)

uint32_t result;
uint32_t counter;

int test(uint32_t& a)
{
  static uint32_t b = 0;
  return a == 0xffffffff ? a++, ++b > 1034594986 ? 0 : 1 : 1;
}

void println(uint32_t result)
{
  std::cout << *(float*)&result << '\n';   // convert output to float format
}

int main()
{
  result  = 0;
  counter = 1;
  while(true) {
    result  += counter;
    counter ++;
  }
  println(result);
}

Comment ça fonctionne:

La #definemodification change la signification de
while(true) {
sur
while(test(counter)) {
Sur les machines qui débordent silencieusement chaque tour de sommation avant un débordement ajoutera 0x80000001 au résultat. Donc, après l'incrément de b, b == résultat lorsque b est pair et (b + 0x80000000) == résultat lorsque b est impair. 1034594986 est une représentation entière du nombre à virgule flottante 1/12. L'ajout de 0x80000001 à cela donnera un entier proche de -1/12 et la fonction de test renverra 0 (faux) et la boucle se terminera.

Et pourquoi vous ne devriez pas essayer de le lancer:

Si vous voulez voir que cela fonctionne, soyez averti: la fonction de test doit être appelée 2 ^ 32 * 1034594986 fois avant de terminer la boucle. (c'est-à-dire pas de votre vivant). Si vous voulez vérifier que cette fonction ne fonctionne pas, utilisez un débogueur ou modifiez le programme pour afficher la valeur de result et b juste après l'instruction b ++. Quand ils sont convaincus qu'ils sont égaux quand b est même juste changer la valeur initiale de b et le compteur à 1034594986. Le programme devrait alors sortir -0.08333 après un certain temps.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.