Programa que adiciona todos os números naturais e gera -1/12 [fechado]

53

Como você deve saber, existe um fato matemático de que se você adicionar todos os números naturais, você terminará com ... -1/12 (consulte a Wikipedia aqui) .

É claro que este é um resultado muito estranho e não pode ser obtido apenas adicionando um número seguido por outro, mas alguns truques matemáticos especiais.

No entanto, sua tarefa é escrever um programa, que parece tentar adicionar todos os números naturais, mas quando você o executa, ele retorna -1/12.

No pseudocódigo, pode ser assim:

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

Você pode fazer isso da maneira que quiser - você pode explorar um pouco de buffer overflow, brincar com erros gerados enquanto alguma variável se torna muito grande ou apenas ocultar a coisa crucial ao longo do código de alguma maneira inteligente. As únicas condições são que o código pareça primeiro tentar adicionar todos os números naturais e, quando executado, retorna -1/12 (em qualquer formato, pode ser decimal, binário, texto, texto ascii art).

Obviamente, o código pode conter muito mais do que o mostrado acima, mas deve ficar claro o suficiente para enganar o leitor.

Este é um concurso de popularidade - vote na idéia mais inteligente!

Paweł Tokarz
fonte
2
Corrigimos suas tags: se é um concurso de popularidade, não pode ser um código de golfe, e temos uma tag secreta para desafios como "escrever código parecido com x, mas com y". Enfim, esse é um desafio bastante decente para um iniciante! :)
Martin Ender
2
@ m.buettner - obrigado por editar tags, sim, sou novo aqui, por isso não conheço todas as tags. Vou tentar seguir as regras!
Paweł Tokarz 27/05
3
Por que todas as respostas, juntamente com a pergunta, foram apenas aprovadas? Downvoter: por favor, deixe um comentário.
Arshajii 27/05
7
A primeira linha não é totalmente verdadeira, dependendo da sua interpretação math.stackexchange.com/questions/39802/…
qwr
3
Estou votando para encerrar esta questão como fora de tópico, porque os desafios secretos não estão mais no tópico neste site. meta.codegolf.stackexchange.com/a/8326/20469
cat

Respostas:

38

C

Devem trabalhar em plataformas onde ambos sizeof(float)e sizeof(int)são 4 e segue o padrão de ponto flutuante IEEE (eu acho).

Versão 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;
}

Resultado: -0.083

Explicação:

Não é uma resposta muito interessante, mas com comentários enganosos.

A soma de 1 a 79774 é 3181985425, que tem a mesma representação binária de -0,08263886719942092895507878125 quando interpretada como uma em floatvez de uma unsigned int.

Observe que !(abs<=0.001)é usado em vez de abs>0.001evitar sair do loop quando a soma atinge 2139135936 (NaN in float). (Agradecemos a @CodesInChaos por sugerir essa ideia em vez de uma isNaNverificação independente .)

Agradecimentos especiais a @Geobits pela idéia de terminar o loop comparando a soma em vez do contador.

Edit: Versão 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;
}

Resultado: -0.083333

Explicação:

Usa o mesmo intPara- floattruque, mas com o --> "tende a" operador aqui. Como todo número é menor que o infinito, o loop não será executado nem uma vez.

Após a conversão float, é comparado com o intnúmero mágico (ou seja, -0,83333 é comparado com 0xBDAAAAAB, ou 3182078635), o que obviamente é diferente.

ace_HongKongIndependence
fonte
3
fazer uma INFINITY # define no topo e substituir o i <INFINITY
ojblass
2
Maneiras interessantes de sair do circuito devem ser consideradas.
Ojblass
Pelo que vale, em hexadecimal 79776é 137A0, o que é ((int) "\rz") << 4. Não tenho certeza o quão útil que é, no entanto
durron597
3
Você pode definir um epsilon para sair do loop. Explicação: "como não podemos correr até o infinito, sairemos assim que convergir em -1/12 dentro da margem de erro de ponto flutuante" ou similar. Você precisará verificar o valor flutuante a cada iteração, mas ele se livrará desse valor ímpar 'infinito'.
Geobits
11
No primeiro código, você pode usar em while(!(abs<delta))vez de while(abs>delta)descartar a verificação NaN.
CodesInChaos
20

Pitão

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

Resultado:

-0.0833333333333

Então qual é o truque?

O truque é: este é um cálculo válido.

primo
fonte
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

(Nota: colar isso em um notebook Mathematica provavelmente revelará o que está acontecendo.)


O que está acontecendo aqui é que estamos definindo o padrão regularização de Sumser Dirichlet regularização (codificado na primeira linha - nota que Mathematica permite que literais Unicode na sua fonte), então a segunda linha, que fora dos olhares de contexto como ele iria produzir infinito, acaba produzindo o valor regularizado -1/12.

arshajii
fonte
3
Tenho certeza de que isso é trapaça, porque você está dizendo ao Mathematica para usar a regularização necessária para fazer a soma funcionar.
Kyle Kanos #
4
@KyleKanos Por que isso é trapaça?
Arshajii 27/05
2
Eu sei que não é código de golfe, mas apenas uma dica: você pode cortar quatro caracteres e apenas adicionar diretamente 68+{0,37,46,37,31,36,40,33,48}, já que Pluspossui o Listableatributo Pessoalmente, acho isso mais idiomático.
David Zhang
3
@arshjii: está enganando, porque você deveria esconder o fato de que o código é enganoso. O uso de um pacote chamado 'regularização' não oculta nada disso. -1 de mim.
Kyle Kanos #
11
@arshajii: Isso esconde um pouco mais e eu diminuí a votação.
Kyle Kanos
10

C

Formata bem a resposta como -1/12, não 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;
}

Como funciona?

Soma todos os números até 656618, excluindo 386106. Isso fornece 215573541165.
Quando interpretado como uma sequência, em uma pequena plataforma endian, você obtém -1/12.

Ugoren
fonte
7

Brainfuck

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

O código apenas avalia 1 + 2 + 3 + ...

... até que i == 256ocorreu um estouro, assumindo o tamanho da célula de 8 bits. Mediante isso, itorna-se 0, os termina de loop e os comentários seguintes são executados.

johnchen902
fonte
Isso não faz sentido. A maioria dos intérpretes compreende, além do fato de que você alega que ele avalia, o 1 + 2 + 3 + ...que significa que 256 teria de ser triangular, i == 256como também afirma, mas 256 não é um número triangular. Além disso, onde seu código é gerado -1/12?
Timtech
@ Timtech O loop termina. É o contador que está transbordando, não a soma. Apenas um pequeno problema: ele sai em 1/12vez de -1/12(Feliz hoje? + .- - .+ + .+ Por favor vote em mim .) Estes quatro .são para saída.
ace_HongKongIndependence
@ace Se fosse o contador, haveria duas opções: 1) Se as células quebrarem, não haveria transbordamento OU 2) se as células não quebrarem, a soma transbordaria muito antes do contador se aproximar 256.
Timtech
@ace Como posso cometer esse erro bobo? Eu consertei, mas agora parece menos disfarçado.
johnchen902
11
As células @ TimTech quebram, então ificam zero quando chegam 256(é isso que eu quis dizer com estouro). Nesse ponto, o loop externo termina e as linhas a seguir (que parecem comentários) são executadas, daí a saída de -1/12.
johnchen902
6

Apenas adicionando uma ofuscação um pouco melhor de deixar o loop na resposta do ás.

#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;
}

Dica: não há excesso ...

Divido por 0 antes de incrementar a variável que inicia o manipulador de exceções

ojblass
fonte
Adicione alguns comentários!
Navin
3
Ele continua somando até que eu fique zero novamente devido ao estouro, momento em que average=sum/i;um SIGFPE, capturado por handler, imprime -1/12.
tomsmeding 27/05
não está adicionando comentários contra o espírito de ser dissimulada?
Ojblass
11
@ojblass Depende de como os comentários são dissimulados. ;-)
Daniel Wagner
8
unsigned int sum=3182065200L; printf("%.3f\n",*(float*) &sum);é uma revelação absoluta de que algo está acontecendo lá, e ver que está no manipulador do SIGFPE torna isso muito óbvio para o meu gosto.
hvd 27/05
4

Perl 6

Calcula a soma usando a função zeta. Eu teria usado [+] 1..*(soma de todos os números entre 1 e infinito), exceto que é executado em tempo infinito.

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: "/";
Konrad Borowski
fonte
Haha, eu estava pensando em postar um resumo simples e afirmar que funcionaria, mas você teria que esperar um tempo infinito antes de imprimir. É bom ver que alguém pensava assim também.
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);
    }
}

Isso adiciona todos os números de 0 ao valor máximo, multiplicado por 12, e também adiciona 1 no final. O resultado é 0, portanto a soma dos números deve ser (0 - 1) / 12.

Explicação:

0xffffffff == -1, o loop não é executado

aditsu
fonte
3

Rubi

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)

Demo

Ok, a suposta semântica e sintaxe de saída aqui faz pouco sentido, mas talvez isso não seja aparente em um relance casual.

Observe também que, de fato, isso é independente da Ruby Platform and Version. Depende de algumas outras constantes serem definidas conforme o esperado.

histocrata
fonte
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;

}

Para lidar com a soma (quase) infinita em um período de tempo razoável, compile com as seguintes opções para algumas otimizações do compilador (necessárias):

$ gcc -trigraphs sum.c

Saída de amostra:

$ ./a.out
$ sum: -0.83333
$
Escova de dente
fonte
11
Se você quiser saber como isso funciona, leia o arquivo .S.
Joshua
8
Seu sinalizador de compilador revela tudo ...
ace_HongKongIndependence
3
“Brechas” comuns que não são mais engraçadas - O ??/truque do trigógrafo já deixou de ser inteligente. :(
doppelgreener
Obrigado pelo link, que explica muito. Existe um link para o FAQ em algum lugar ou preciso procurar sempre?
@tolos Você pode favorito, ou é uma das únicas perguntas sob a metatag [ faq ], ou encontrá-lo através das Perguntas frequentes da comunidade .
Doppelgreener
3

Java

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

Em teoria, isso será impresso true. No entanto, acho que meu computador se desfaz em pó antes de terminar de executá-lo.

Dawood diz restabelecer Monica
fonte
11
Por que deveria ser verdade? Por que você espera que a soma atinja o -1/12?
Paweł Tokarz
@ PawełTokarz Eu não sou um especialista em Java, então não posso ter certeza, mas vale a pena notar que, já que o Java usa a divisão inteira, -1/12é absolutamente zero. Então, eu suponho que é algum tipo de comportamento de estouro que faz com que o loop termine e, coincidentemente, sumtransborda para zero?
ace_HongKongIndependence
Sim, um estouro fará o loop parar quando atingir o máximo long. O universo provavelmente não existirá mais até então, mas isso é apenas teórico, certo? E sim, todos os 32 bits inferiores sumserão zero - e é por isso que é importante sumser um int, não um long. Obviamente, como o @ace disse, o Java usa a divisão inteira para avaliar -1/12, então é zero.
Dawood diz que restabelece Monica
11
long.MAX_VALUE é 9.223.372.036.854.775.807. Isso é grande, mas incrementar apenas 1 milhão de vezes por segundo levaria você para lá em apenas algumas centenas de milhares de anos. Você precisaria apenas de 4 bilhões de incrementos por segundo para terminar dentro da vida humana. Não estamos falando de escalas de tempo do "fim do universo", aqui, a menos que você saiba algo que não está compartilhando com o resto de nós.
User19057
11
@ user19057 Obrigado pela correção. Você está certo, é claro, embora eu adoraria saber por que você acha que o universo vai durar mais de 100.000 anos a mais. De qualquer forma, não vou ficar esperando o programa terminar de executar. Há grama para eu assistir crescendo.
Dawood diz que restabelece 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);
        }
    }
}

Como funciona:

Java usa codificação UTF-8 para tudo. Eu uso truеcom um Y cirílico no final, em vez do habitual 'e' (graças a @CodesInChaos), que é static booleaninicializado false. Existe import ȷava.math.BigDecimal;um j sem pontos em vez de import java.math.BigDecimal; Meu ȷava.math.BigDecimaldefine public static boolean truе = false;e public String toString() { return "-1/12"; }para citar apenas dois hacks óbvios.

Gostaria de poder postar isso como um spoiler, mas não sei como. Aqui está o restante do código que está oculto.

// 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;
    }
}
OldCurmudgeon
fonte
O ŧrue / true é claramente visível, mas a diferença entre ȷava e java é tão pequena que tive que ler o comentário algumas vezes para identificar esse ponto!
Paweł Tokarz 28/05
11
@OldCurmudgeon Acho que existe uma aparência perfeita para e no alfabeto cirílico: Ye (cirílico)
CodesInChaos
11
Se não me engano, você publica código incompleto. Se você importar pacotes não padrão, também deverá postar o código deles.
Ugoren
11
O cíclico 'e' é muito legal para tornar as coisas ilegíveis. Imagine: se (verdadeiro! = Verdadeiro) {return true} else {return true}; : D
Paweł Tokarz
11
@Andrew G true!
Paweł Tokarz
2

Não há soluções Haskell, inaceitáveis!

Podemos utilizar as infinitas listas de Haskell para obter uma resposta exata!

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)

A solução é bastante simples quando você leva em consideração as flechas ....

Então qual é o truque?

Não há extensão de idioma para definir comentários de linha única

recursion.ninja
fonte
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);
}

De acordo com o padrão C, isso pode muito bem ser impresso, Answer = -1/12pois haverá um estouro de número inteiro assinado que é um comportamento indefinido. Encontrar um compilador que faça isso é deixado como um exercício para o leitor.

Geoff Reedy
fonte
esse código nunca chegará aoprintf
Bogdacutu 28/05
5
Prefiro respostas que geralmente produzem a saída necessária, não apenas "permitam".
Paŭlo Ebermann 28/05
2

Mathematica

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

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

insira a descrição da imagem aqui

Simon Woods
fonte
2
Você se importaria de dar uma explicação sobre o que está acontecendo aqui?
ace_HongKongIndependence
Haha, muito engraçado, e pode ser um bom material para testar se um novato no Mathematica entendeu a sintaxe básica ou não!
xzczd
1

Python 3.x

Meio novo aqui. Alguma dica?

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())
Obversidade
fonte
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 );

Como funciona:

1:

Os comentários do código são (sem surpresa) todas mentiras, mas são uma distração da ofuscação principal.

2:

~ e ^ são os operadores "bit a bit não" e "bit a bit xor". Resultando em um sendo redefinido para -12.

3:

add está definido para a função de seta ECMAScript 6 "(resultado, contador) => (resultado + contador, contador)", que não faz o que os comentários sugerem - em vez disso, retorna apenas a última expressão "contador" e é efetivamente um no-op.

4:

Existem duas variáveis ​​de "resultado" - uma é escrita em caracteres ASCII puros (no escopo global) e a outra possui um "s" cirílico Unicode (dentro do escopo da função anônima usada para definir adição). "resultado = 1" redefine o valor no escopo global e a segunda linha "resultado = (0 |! resultado) / um;" também tem o lado esquerdo referente à variável "resultado" no escopo global, mas o "resultado" no lado direito da expressão refere-se ao escopo da função e tem o valor 0 (em vez do valor esperado de 1 ), então o valor de! resultado / um = -1/12.

MT0
fonte
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';
}

Se os dois #defines forem removidos, o código ainda será válido em C ++ e tentará (mas é claro que falhará) calcular a soma de todos os números inteiros.

Como funciona:

As diretivas do pré-processador transformam o código principal em:

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

Além de declarar um Aobjeto, as três primeiras linhas são apenas ofuscação. A última linha faz todo o trabalho usando o operador sobrecarregado <<em um Aobjeto.

Dado o pseudocódigo dos pôsteres, não pude resistir ao adicionar este. Ele usa a mesma idéia básica e outra pequena, mas não acho que seja tão elegante.

#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);
}

Como funciona:

A #definemuda o significado de
while(true) {
a
while(test(counter)) {
Em máquinas que silenciosamente transbordam cada rodada do somatório antes de um estouro irá adicionar 0x80000001 para resultar. Portanto, após o incremento de b, b == resulta quando b é par e (b + 0x80000000) == resulta quando b é ímpar. 1034594986 é uma representação inteira do número de ponto flutuante 1/12. Adicionar 0x80000001 a isso resultará no número inteiro próximo a -1/12 e a função de teste retornará 0 (falso) e o loop será encerrado.

E por que você não deve tentar executá-lo:

Se você quiser ver que as obras são avisadas: a função de teste deve ser chamada 2 ^ 32 * 1034594986 vezes antes de terminar o loop. (ou seja, não em sua vida). Se você deseja verificar se a função funciona como indicado, use um depurador ou altere o programa para ver o valor do resultado eb logo após a instrução b ++. Quando estiver satisfeito que eles são iguais quando b é apenas, altere o valor inicial de be contador para 1034594986. O programa deve então emitir -0,08333 após algum tempo.

Lars Betak
fonte