Program, który dodaje wszystkie liczby naturalne i daje -1/12 [zamknięty]

53

Jak zapewne wiecie, istnieje matematyczna frajda, że ​​po dodaniu wszystkich liczb naturalnych otrzymamy ... -1/12 (patrz Wikipedia tutaj) .

Oczywiście jest to bardzo dziwny wynik i nie można go uzyskać, dodając tylko jedną liczbę, a następnie inną, ale niektóre specjalne sztuczki matematyczne.

Twoim zadaniem jest jednak napisanie programu, który wygląda tak , jakby próbował dodać wszystkie liczby naturalne, ale po uruchomieniu program zwraca -1/12.

W pseudokodzie może to wyglądać tak:

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

Możesz to zrobić w dowolny sposób - możesz wykorzystać przepełnienie bufora, grać z wyrzuconymi błędami, podczas gdy jakaś zmienna staje się zbyt duża lub po prostu ukryć kluczowe elementy w kodzie w sprytny sposób. Jedynymi warunkami jest to, że kod powinien na początku wyglądać, jakby próbował dodać wszystkie liczby naturalne, a po uruchomieniu zwraca -1/12 (w dowolnym formacie, może być dziesiętny, binarny, tekstowy, ascii).

Kod może oczywiście zawierać znacznie więcej niż pokazano powyżej, ale powinien być wystarczająco jasny, aby oszukać czytelnika.

To konkurs popularności - głosuj na najmądrzejszy pomysł!

Paweł Tokarz
źródło
2
Naprawiono tagi: jeśli jest to konkurs popularności, nie może to być gra w golfa, a my mamy podstępny tag dla takich wyzwań, jak: „pisz kod, który wygląda jak x, ale robi y”. W każdym razie jest to całkiem przyzwoite wyzwanie dla nowicjusza! :)
Martin Ender
2
@ m.buettner - dziękuję za edycję tagów, tak, jestem tu nowy, więc nie znam wszystkich tagów. Postaram się przestrzegać zasad!
Paweł Tokarz
3
Dlaczego wszystkie odpowiedzi wraz z pytaniem zostały po prostu zanegowane? Downvoter: proszę zostawić komentarz.
arshajii
7
Pierwsza linia nie jest do końca prawdziwa, w zależności od twojej interpretacji math.stackexchange.com/questions/39802/…
qwr
3
Głosuję za zamknięciem tego pytania jako nie na temat, ponieważ słabe wyzwania nie są już na ten temat na tej stronie. meta.codegolf.stackexchange.com/a/8326/20469
kot

Odpowiedzi:

38

do

Powinien działać na platformach gdzie zarówno sizeof(float)i sizeof(int)są 4 i następujący standard zmiennoprzecinkowej IEEE (chyba).

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

Wynik: -0.083

Wyjaśnienie:

Niezbyt interesująca odpowiedź, ale z wprowadzającymi w błąd komentarzami.

Suma od 1 do 79774 wynosi 3181985425, która ma taką samą reprezentację binarną jak -0,082638867199420928955078125, gdy jest interpretowana jako floatzamiast unsigned int.

Zauważ, że !(abs<=0.001)jest używany zamiast abs>0.001unikać wychodzenia z pętli, gdy suma osiągnie 2139135936 (wejście NaN float). (Dzięki @CodesInChaos za zasugerowanie tego pomysłu zamiast niezależnej isNaNkontroli.)

Specjalne podziękowania dla @Geobits za pomysł zakończenia pętli poprzez porównanie sumy zamiast licznika.

Edycja: wersja 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;
}

Wynik: -0.083333

Wyjaśnienie:

Używa tego samego int-to- floattricka, ale z --> „ma tendencję do” operator tutaj. Ponieważ każda liczba jest mniejsza niż nieskończoność, pętla nie zostanie wykonana ani razu.

Po przekonwertowaniu na floatto jest porównywane z intliczbą magiczną (tj. -0,83333 jest porównywane z 0xBDAAAAAB, lub 3182078635), która oczywiście jest inna.

ace_HongKongIndependence
źródło
3
utwórz #define INFINITY u góry i zastąp i <INFINITY
ojblass
2
Należy rozważyć interesujące sposoby wyjścia z pętli.
ojblass
Za to, co jest warte, w hex 79776jest 137A0, co jest ((int) "\rz") << 4. Nie jestem jednak pewien, jak to jest przydatne
durron597
3
Możesz zdefiniować epsilon, aby wyjść z pętli. Objaśnienie: „ponieważ nie możemy uruchomić się w nieskończoność, wybuchniemy, gdy zbiegnie się do -1/12 w zmiennoprzecinkowym marginesie błędu” lub podobnie. Będziesz musiał sprawdzać wartość zmiennoprzecinkową przy każdej iteracji, ale pozbędzie się ona tej dziwnej wartości „nieskończoności”.
Geobity
1
W pierwszym kodzie możesz użyć while(!(abs<delta))zamiast while(abs>delta)upuścić czek NaN.
CodesInChaos
20

Pyton

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

Wynik:

-0.0833333333333

Więc jaka jest sztuczka?

Sztuka polega na tym: jest to prawidłowe obliczenie.

primo
źródło
18

Matematyka

\: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

(Uwaga: wklejenie tego do notatnika Mathematica prawdopodobnie ujawni, co się dzieje).


Co tu się dzieje jest to, że jesteśmy ustawienie domyślne regularyzacji o Sumbyć Dirichlet uregulowanie (zakodowane w pierwszej linii - pozwala zauważyć, że Mathematica literałów Unicode w jego źródła), więc druga linia, która z kontekstu wygląda byłoby produkować nieskończoność, ostatecznie wytwarza wartość regularną -1/12.

arshajii
źródło
3
Jestem prawie pewien, że to oszustwo, ponieważ mówisz Mathematice, aby użyła regularyzacji potrzebnej, aby suma zadziałała.
Kyle Kanos
4
@KyleKanos Dlaczego to oszustwo?
arshajii
2
Wiem, że to nie jest kod golfowy, ale wskazówka: możesz wyciąć cztery znaki i po prostu bezpośrednio dodać 68+{0,37,46,37,31,36,40,33,48}, ponieważ Plusma ten Listableatrybut. Osobiście uważam to za bardziej idiomatyczne.
David Zhang
3
@arshjii: to oszustwo, ponieważ powinieneś ukrywać fakt, że kod wprowadza w błąd. Korzystanie z pakietu o nazwie „regularyzacja” wcale tego nie ukrywa. -1 ode mnie.
Kyle Kanos
1
@arshajii: To trochę bardziej to ukrywa i nie oceniłem tego.
Kyle Kanos
10

do

Ładnie formatuje odpowiedź jako -1/12nie 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;
}

Jak to działa?

Sumuje wszystkie liczby do 656618, z wyjątkiem 386106. Daje to 215573541165.
Po zinterpretowaniu jako ciąg znaków, na małej platformie Endian, dostajesz -1/12.

ugoren
źródło
7

Brainfuck

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

Kod ocenia tylko 1 + 2 + 3 + ...

... aż do i == 256wystąpienia przepełnienia, zakładając rozmiar komórki 8-bitów. Po tym istaje się 0, pętla kończy się, a następujące komentarze są wykonywane.

johnchen902
źródło
To nie ma sensu. Większość tłumaczy interpretuje, a także fakt, że twierdzisz, że to ocenia, 1 + 2 + 3 + ...co oznacza, że ​​256 musiałoby być trójkątne, i == 256jak również twierdzisz, ale 256 nie jest liczbą trójkątną. Ponadto, gdzie wyprowadza twój kod -1/12?
Timtech
@Timtech Pętla się kończy. Przepełnia się licznik, a nie suma. Tylko jeden mały problem: generuje 1/12zamiast -1/12(Szczęśliwy dzisiaj? + .- - .+ + .+ Proszę głosować za mną .) Te cztery .służą do generowania.
ace_HongKongIndependence
@ace Jeśli byłby to licznik, istniałyby dwie opcje: 1) Jeśli komórki się zawijają, wówczas nie byłoby przepełnienia LUB 2) Jeśli komórki się nie zawijają, wówczas suma przepełniłaby się znacznie zanim licznik się zbliżył 256.
Timtech
@ace Jak mogę popełnić ten głupi błąd? Naprawiłem to, ale teraz wydaje się mniej podstępne.
johnchen902
1
@Timtech Komórki się zawijają, więc istają się zerowe, gdy się do nich dostać 256(to miałem na myśli przez przepełnienie). W tym momencie pętla zewnętrzna kończy się, a następujące po niej linie (które wydają się komentarzem) są wykonywane, stąd wyjście -1/12.
johnchen902
6

Po prostu dodanie trochę lepszego zaciemnienia wyjścia z pętli do odpowiedzi asa.

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

Wskazówka, że ​​nie ma przelewu ...

Dzielę przez 0, zanim zwiększę zmienną i uruchamiam procedurę obsługi wyjątków

ojblass
źródło
Dodaj kilka komentarzy!
Navin
3
Po prostu sumuje, dopóki I nie osiągnie zera z powodu przepełnienia, w którym to momencie average=sum/i;SIGFPE zostaje złapany przez handlerdrukowanie -1/12.
tomsmeding
nie dodaje komentarzy wbrew duchowi bycia podstępnym?
ojblass
1
@ojblass Zależy od tego, jak podstępne są komentarze. ;-)
Daniel Wagner
8
unsigned int sum=3182065200L; printf("%.3f\n",*(float*) &sum);to martwa gratka, że ​​coś się tam dzieje, a fakt, że jest w module obsługi SIGFPE, sprawia, że ​​jest to zbyt oczywiste dla moich gustów.
hvd
4

Perl 6

Oblicza sumę za pomocą funkcji zeta. Użyłbym [+] 1..*(suma wszystkich liczb od 1 do nieskończoności), z wyjątkiem tego, że działa w nieskończonym czasie.

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
źródło
Haha, myślałem o opublikowaniu prostego podsumowania i twierdzeniu, że to zadziała, ale będziesz musiał czekać na nieskończony czas, zanim zostanie wydrukowany. Miło widzieć, że ktoś tak też myślał.
Kyle Kanos
4

Jawa

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

Dodaje to wszystkie liczby od 0 do wartości maksymalnej, pomnożone przez 12, a także dodaje 1 na końcu. Wynik to 0, dlatego suma liczb musi wynosić (0 - 1) / 12.

Wyjaśnienie:

0xffffffff == -1, pętla w ogóle się nie wykonuje

aditsu
źródło
3

Rubin

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)

Próbny

Okej, przypuszczalna semantyka i składnia wyjściowa tutaj nie mają większego sensu, ale może nie jest to oczywiste na pierwszy rzut oka.

Zauważ też, że jest to w rzeczywistości niezależne od platformy Ruby i wersji. Zależy to od niektórych innych stałych zdefiniowanych zgodnie z oczekiwaniami.

histocrat
źródło
3

do

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

}

Aby poradzić sobie z (prawie) nieskończoną sumą w rozsądnym czasie, skompiluj z następującymi opcjami dla niektórych optymalizacji kompilatora (wymagane):

$ gcc -trigraphs sum.c

Przykładowe dane wyjściowe:

$ ./a.out
$ sum: -0.83333
$
Szczoteczka do zębów
źródło
1
Jeśli chcesz wiedzieć, jak to działa, przeczytaj plik .S.
Jozuego
8
Flaga kompilatora oddaje wszystko ...
ace_HongKongIndependence
3
Standardowe „luki”, które nie są już śmieszne - ??/sztuczka z trigrafią już dawno przestała być sprytna. :(
doppelgreener
Dziękuję za link, który wiele wyjaśnia. Czy jest gdzieś link do FAQ, czy muszę go za każdym razem szukać?
@tolos Możesz to ulubione lub jedno z niewielu pytań pod meta [ faq ] lub znaleźć je w FAQ społeczności .
doppelgreener
3

Jawa

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

Teoretycznie to zostanie wydrukowane true. Myślę jednak, że mój komputer rozpadnie się w pył, zanim skończy działać.

Dawood ibn Kareem
źródło
1
Dlaczego to ma być prawdą? Dlaczego oczekujesz, że suma osiągnie -1/12?
Paweł Tokarz
@ PawełTokarz Nie jestem ekspertem od Java, więc nie jestem pewien, ale warto zauważyć, że ponieważ Java korzysta z dzielenia liczb całkowitych, -1/12jest to zero. Zakładam więc, że jest to rodzaj przepełnienia, które powoduje zakończenie pętli i przypadkowe sumprzepełnienie do zera?
ace_HongKongIndependence
Tak, przepełnienie spowoduje zatrzymanie pętli, gdy osiągnie maksimum long. Wszechświat prawdopodobnie już wtedy nie będzie istniał, ale to tylko teoretyczne, prawda? I tak, wszystkie dolne 32 bity sumbędą wynosić zero - dlatego ważne jest, sumaby być an int, a nie long. Oczywiście, jak powiedział @ace, Java używa dzielenia liczb całkowitych do oceny -1/12, więc jest zero.
Dawood ibn Kareem
1
long.MAX_VALUE wynosi 9 223 372,036,854,775,807. To duże, ale zwiększenie zaledwie miliona razy na sekundę doprowadziłoby cię tam za kilkaset tysięcy lat. Potrzebujesz tylko około 4 miliardów przyrostów na sekundę, aby zakończyć w ciągu ludzkiego życia. Nie mówimy tutaj o skalach czasu „końca wszechświata”, chyba że wiesz coś, czego nie dzielisz się z resztą z nas.
user19057
1
@ user19057 Dzięki za korektę. Oczywiście masz całkowitą rację, chociaż chciałbym wiedzieć, dlaczego według ciebie wszechświat przetrwa ponad 100 000 lat. W każdym razie nie zamierzam siedzieć i czekać, aż mój program się zakończy. Mam trawę do oglądania, jak rośnie.
Dawood ibn Kareem
3

Jawa

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

Jak to działa:

Java do wszystkiego używa kodowania UTF-8. Używam truеz Cyrylicą Ye na końcu zamiast zwykłego „e” (dzięki @CodesInChaos), który jest static booleaninicjalizowany false. Jest tam import ȷava.math.BigDecimal;bez kropki j zamiast import java.math.BigDecimal; Moje ȷava.math.BigDecimaldefinicje public static boolean truе = false;i public String toString() { return "-1/12"; }żeby wymienić tylko dwa oczywiste hacki.

Chciałbym móc zamieścić to jako spoiler, ale nie mogę wymyślić, jak to zrobić. Oto reszta kodu, który jest podstępnie ukryty.

// 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
źródło
Prawda / prawda jest wyraźnie widoczna, ale różnica między avaą a Javą jest tak mała, że ​​musiałem przeczytać komentarz kilka razy, aby zauważyć tę kropkę!
Paweł Tokarz
1
@OldCurmudgeon Myślę, że istnieje idealny wygląd podobny do e w cyrylicy: Ye (Cyrylica)
CodesInChaos
1
Jeśli się nie mylę, publikujesz niekompletny kod. Jeśli importujesz niestandardowe paczki, powinieneś również opublikować ich kod.
ugoren
1
Cyrylica „e” jest całkiem fajna, ponieważ sprawia, że ​​rzeczy są nieczytelne. Wyobraź sobie: if (true! = True) {return true} else {return true}; : D
Paweł Tokarz
1
@Andrew G prawda!
Paweł Tokarz
2

Brak rozwiązań Haskell, nie do przyjęcia!

Możemy wykorzystać nieskończone listy Haskella, aby uzyskać dokładną odpowiedź!

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)

Rozwiązanie jest dość proste, jeśli weźmiesz pod uwagę strzałki ....

Więc jaka jest sztuczka?

Brak rozszerzenia języka do zdefiniowania komentarza jednowierszowego

recursion.ninja
źródło
2

do

#include <stdio.h>

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

Zgodnie ze standardem C można to bardzo dobrze wydrukować, Answer = -1/12ponieważ wystąpi przepełnienie liczby całkowitej, które jest niezdefiniowanym zachowaniem. Znalezienie kompilatora, który to zrobi, pozostawia czytelnikowi ćwiczenie.

Geoff Reedy
źródło
ten kod nigdy nie dotrze doprintf
Bogdacutu
5
Wolę odpowiedzi, które zwykle dają wymagane wyniki, a nie tylko „pozwalają”.
Paŭlo Ebermann
2

Matematyka

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

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

wprowadź opis zdjęcia tutaj

Simon Woods
źródło
2
Czy mógłbyś wyjaśnić, co się tutaj dzieje?
ace_HongKongIndependence
Haha, całkiem zabawne i może być dobrym materiałem do sprawdzenia, czy początkujący Mathematica zrozumiał podstawową składnię, czy nie!
xzczd
1

Python 3.x

Trochę nowy tutaj. Jakieś wskazówki?

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())
Oversity
źródło
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 );

Jak to działa:

1:

Komentarze do kodu to (co nie dziwi) wszystkie kłamstwa, ale odwracają uwagę od głównego zaciemnienia.

2:

~ i ^ to operatory „nie bitowe” i „bitowe xor”. W wyniku tego jeden został ponownie zdefiniowany na -12.

3:

add jest ustawiony na funkcję strzałki ECMAScript 6 „(wynik, licznik) => (wynik + licznik, licznik)”, który nie robi tego, co sugerują komentarze - zamiast tego zwraca tylko ostatnie wyrażenie „licznik” i działa skutecznie brak op.

4:

Istnieją dwie zmienne „wynikowe” - jedna jest zapisana czystymi znakami ASCII (w zakresie globalnym), a druga ma cyrylicę „s” w Unicode (w zakresie anonimowej funkcji użytej do zdefiniowania add). „wynik = 1” resetuje wartość w zakresie globalnym, a drugi wiersz „wynik = (0 |! wynik) / jeden;” ma także lewą stronę odwołującą się do zmiennej „wynik” w zakresie globalnym, ale „wynik” po prawej stronie wyrażenia odnosi się do zakresu funkcji i ma wartość 0 (zamiast oczekiwanej wartości 1 ), więc wartość! result / one = -1/12.

MT0
źródło
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';
}

Jeśli dwa #defines zostaną usunięte, kod nadal będzie prawidłowym kodem C ++ i faktycznie spróbuje (ale oczywiście nie powiedzie się) obliczyć sumę wszystkich liczb całkowitych.

Jak to działa:

Dyrektywy preprocesora zamieniają główny kod w:

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

Oprócz zadeklarowania Aobiektu pierwsze trzy wiersze są po prostu zaciemnieniem. Ostatnia linia wykonuje całą pracę przy użyciu przeciążonego operatora <<na Aobiekcie.

Biorąc pod uwagę pseudokod plakatu, nie mogłem się powstrzymać przed dodaniem tego. Wykorzystuje ten sam podstawowy i kolejny mały pomysł, ale nie sądzę, że jest tak elegancki.

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

Jak to działa:

Do #definezmienia znaczenie
while(true) {
do
while(test(counter)) {
W przypadku maszyn, które cicho porwała każdą rundę sumowania przed przelewem doda 0x80000001 do rezultatu. Stąd po inkrementacji b, b == wynik, gdy b jest parzyste i (b + 0x80000000) == wynik, gdy b jest nieparzyste. 1034594986 jest całkowitą reprezentacją liczby zmiennoprzecinkowej 1/12. Dodanie do tego 0x80000001 spowoduje, że liczba całkowita będzie bliska -1/12, a funkcja testowa zwróci 0 (fałsz), a pętla zakończy się.

I dlaczego nie powinieneś próbować go uruchomić:

Jeśli chcesz zobaczyć, że działa ostrzeżenie: testową funkcję należy wywołać 2 ^ 32 * 1034594986 razy przed zakończeniem pętli. (tj. nie za twojego życia). Jeśli chcesz sprawdzić, czy ta funkcja działa zgodnie z instrukcją, użyj debugera lub zmień program, aby zobaczyć wartość wyniku ib zaraz po instrukcji b ++. Po upewnieniu się, że są one równe, gdy b jest nawet po prostu zmień wartość początkową b i licznik na 1034594986. Program powinien następnie wyprowadzić -0,08333 po pewnym czasie.

Lars Betak
źródło