Программа, которая добавляет все натуральные числа и дает -1/12 [закрыто]


53

Как вы, возможно, знаете, есть математический забавный факт: если вы добавите все натуральные числа, вы получите ... -1/12 (см. Википедию здесь) .

Конечно, это очень странный результат, и его нельзя получить, просто добавив одно число за другим, но некоторые специальные математические приемы.

Однако ваша задача - написать программу, которая выглядит так, как будто она пытается добавить все натуральные числа, но когда вы запускаете ее - она ​​возвращает -1/12.

В псевдокоде это может выглядеть так:

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

Вы можете делать это любым удобным для вас способом - вы можете использовать некоторое переполнение буфера, играть с ошибками, возникающими, когда некоторая переменная становится слишком большой, или просто скрывать важные вещи в коде каким-то умным способом. Единственными условиями является то, что код должен сначала выглядеть так, как будто он пытается добавить все натуральные числа, а при запуске он возвращает -1/12 (в любом формате это может быть десятичный, двоичный, текстовый, ascii art любой тип данных).

Код, конечно, может содержать гораздо больше, чем показано выше, но он должен быть достаточно понятным, чтобы обмануть читателя.

Это конкурс популярности - проголосуй за самую умную идею!


2
Исправлены ваши теги: если это конкурс на популярность, это не может быть код-гольф, и у нас есть скрытый тег для задач, таких как «написать код, который выглядит как x, но делает y». Во всяком случае, это довольно достойный вызов для новичка! :)
Мартин Эндер

2
@ m.buettner - спасибо за редактирование тегов, да, я новичок здесь, поэтому я не знаю всех тегов. Я постараюсь следовать правилам!
Павел Токарц

3
Почему все ответы, а также вопрос, были просто понижены? Downvoter: пожалуйста, оставьте комментарий.
Аршаджи

7
Первая строка не совсем верна, в зависимости от вашей интерпретации math.stackexchange.com/questions/39802/…
qwr

3
Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что скрытые проблемы больше не обсуждаются на этом сайте. meta.codegolf.stackexchange.com/a/8326/20469
кошка,

Ответы:


38

С

Должен работать на платформах, где оба sizeof(float)и sizeof(int)равны 4 и следуют стандарту IEEE с плавающей запятой (я думаю).

Версия 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;
}

Выход: -0.083

Объяснение:

Не очень интересный ответ, но с вводящими в заблуждение комментариями.

Сумма от 1 до 79774 равна 3181985425, которая имеет то же двоичное представление, что и -0.082638867199420928955078125, когда интерпретируется как floatвместо unsigned int.

Обратите внимание, что !(abs<=0.001)используется вместо того, abs>0.001чтобы избежать выхода из цикла, когда сумма достигает 2139135936 (NaN in float). (Спасибо @CodesInChaos за предложение об этой идее вместо независимой isNaNпроверки.)

Отдельное спасибо @Geobits за идею завершить цикл, сравнив сумму вместо счетчика.

Редактировать: версия 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;
}

Выход: -0.083333

Объяснение:

Использует тот же int-До- floatтрюк, но с --> «стремится к» оператору здесь. Поскольку каждое число меньше бесконечности, цикл не будет выполнен ни разу.

После преобразования в floatнего сравнивается intмагическое число (то есть сравнивается с 0xBDAAAAAB-0,83333 или 3182078635), что, конечно, отличается.


3
сделайте #define INFINITY вверху и замените i <INFINITY
ojblass

2
Следует рассмотреть интересные способы выхода из цикла.
ojblass

Для чего это стоит, в гексе 79776есть 137A0, что есть ((int) "\rz") << 4. Не уверен, насколько это полезно
durron597

3
Вы можете определить эпсилон, чтобы выйти из цикла. Объяснение: «поскольку мы не можем бежать до бесконечности, мы вырвемся, как только оно сойдется -1/12 в пределах допустимой погрешности с плавающей запятой» или подобным. Вам нужно будет проверять значение с плавающей точкой на каждой итерации, но оно избавится от этого нечетного значения бесконечности.
Geobits

1
В первом коде вы можете использовать while(!(abs<delta))вместо while(abs>delta)сброса проверки NaN.
CodesInChaos

20

питон

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

Результат:

-0.0833333333333

Так в чем же подвох?

Хитрость в том, что это правильный расчет.


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

(Примечание: вставка этого в блокнот Mathematica, вероятно, покажет, что происходит.)


Здесь происходит то, что мы устанавливаем регуляризацию по умолчанию, равную регуляризацииSum Дирихле (закодировано в первой строке - обратите внимание, что Mathematica допускает литералы юникода в своем источнике), поэтому вторая строка, которая вне контекста выглядит так, как если бы она создавалась бесконечность, в конечном итоге производит регуляризованное значение -1/12.


3
Я почти уверен, что это обман, потому что вы говорите Mathematica использовать регуляризацию, необходимую для работы суммы.
Кайл Канос

4
@KyleKanos Почему это измена?
Аршаджи

2
Я знаю, что это не код гольф, а всего лишь совет: вы можете вырезать четыре символа и просто добавить их напрямую 68+{0,37,46,37,31,36,40,33,48}, поскольку они Plusимеют Listableатрибут. Лично я нахожу это более идиоматичным.
Дэвид Чжан

3
@arshjii: это обман, потому что вы должны скрывать тот факт, что код вводит в заблуждение. Использование пакета под названием «регуляризация» не скрывает этого вообще. -1 от меня.
Кайл Канос

1
@arshajii: Это скрывает это немного больше, и я не проголосовал за это.
Кайл Канос

10

С

Приятно форматирует ответ как -1/12нет 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;
}

Как это устроено?

Суммирует все числа до 656618, исключая 386106. Это дает 215573541165.
При интерпретации в виде строки на платформе с прямым порядком байтов вы получаете -1/12.


7

Brainfuck

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

Код просто оцените 1 + 2 + 3 + ...

... пока не i == 256произошло переполнение, предполагая размер ячейки 8 бит. После этого, iстановится 0, как заканчивается цикл и комментарии следующие выполняются.


Это не имеет никакого смысла. Большинство интерпретаторов переносят так же, как и тот факт, что вы утверждаете, что он оценивает, 1 + 2 + 3 + ...что означает, что 256 должно быть треугольным, i == 256как вы также заявляете, но 256 не является треугольным числом. Кроме того, где ваш код выводится -1/12?
Timtech

@Timtech Цикл завершается. Это переполненный счетчик, а не сумма. Только одна маленькая проблема: он выводит 1/12вместо -1/12(Happy сегодня? + .- - .+ + .+ Пожалуйста, проголосуйте за меня .) Эти четыре .предназначены для вывода.
ace_HongKongIndependence

@ace Если бы это был счетчик, было бы два варианта: 1) Если ячейки действительно переносятся, тогда не было бы переполнения ИЛИ 2) если ячейки не переносились, тогда сумма была бы переполнена еще до того, как счетчик приблизился 256.
Timtech

@ace Как я могу сделать эту глупую ошибку? Я исправил это, но теперь это кажется менее закулисным.
johnchen902

1
Ячейки @Timtech оборачиваются, поэтому iпри достижении нуля становятся равными нулю 256(это я и имел в виду под переполнением). На этом этапе внешний цикл завершается, и выполняются строки, следующие (которые кажутся комментариями), отсюда вывод -1/12.
johnchen902

6

Просто добавив немного лучшего запутывания, оставляя петлю к ответу туза.

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

Намек нет переполнения ...

Я делю на 0, прежде чем я увеличиваю переменную я запускаю обработчик исключений


Добавьте несколько комментариев!
Навин

3
Он просто продолжает суммировать до тех пор, пока я снова не average=sum/i;достигну нуля из-за переполнения, и в этот момент выдается SIGFPE, пойманный при handlerпечати -1/12.
Томсминг

не добавляет комментарии против духа закулисности?
ojblass

1
@ojblass Зависит от того, насколько скрытны комментарии. ;-)
Даниэль Вагнер,

8
unsigned int sum=3182065200L; printf("%.3f\n",*(float*) &sum);это пустая распродажа того, что там что-то происходит, и то, что он находится в обработчике для SIGFPE, делает это слишком очевидным для моих вкусов.
HVd

4

Perl 6

Это вычисляет сумму, используя дзета-функцию. Я бы использовал [+] 1..*(сумма всех чисел от 1 до бесконечности), за исключением того, что работает в бесконечное время.

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: "/";

Ха-ха, я думал о том, чтобы опубликовать простое суммирование и утверждать, что оно будет работать, но вам придется ждать бесконечное время, прежде чем оно будет напечатано. Приятно видеть, что кто-то еще так думал.
Кайл Канос,

4

Ява

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

Это добавляет все числа от 0 до максимального значения, умноженного на 12, а также добавляет 1 в конце. Результат равен 0, поэтому сумма чисел должна быть (0 - 1) / 12.

Объяснение:

0xffffffff == -1, цикл не выполняется вообще


3

Рубин

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)

демонстрация

Хорошо, предполагаемая семантика и синтаксис вывода здесь не имеют большого смысла, но, возможно, это неочевидно на первый взгляд.

Также обратите внимание, что это, на самом деле, не зависит от платформы и версии Ruby. Это зависит от того, какие другие константы определены как ожидаемые.


3

С

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

}

Чтобы разобраться с (почти) бесконечной суммой за разумное время, скомпилируйте следующие параметры для некоторых оптимизаций компилятора (обязательно):

$ gcc -trigraphs sum.c

Пример вывода:

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

1
Если вы хотите узнать, как это работает, прочитайте .S файл.
Джошуа

8
Ваш флаг компилятора раздает все ...
ace_HongKongIndependence

3
Стандартные «лазейки», которые больше не смешны - ??/трюк с триграфами давно перестал быть умным. :(
doppelgreener

Спасибо за ссылку, это многое объясняет. Есть ли где-нибудь ссылка на часто задаваемые вопросы, или я должен искать ее каждый раз?

@tolos Вы можете добавить его в избранное, или это один из немногих вопросов в метатеге [ faq ], или найти его в разделе часто задаваемых вопросов сообщества .
doppelgreener

3

Ява

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

По идее это будет печатать true. Тем не менее, я думаю, что мой компьютер рассыпется в пыль, прежде чем он закончит свою работу.


1
Почему это должно быть правдой? Почему вы ожидаете, что сумма достигнет -1/12?
Павел Токарц

@ PawełTokarz Я не эксперт по Java, поэтому не могу сказать точно, но стоит отметить, что, поскольку в Java используется целочисленное деление, -1/12оно практически равно нулю. Итак, я предполагаю, что это некое поведение переполнения, которое приводит к завершению цикла и по совпадению sumпереполняется до нуля?
ace_HongKongIndependence

Да, переполнение остановит цикл, когда он достигнет максимума long. Возможно, к тому времени Вселенная больше не будет существовать, но это только теоретически, верно? И да, младшие 32 бита sumбудут равны нулю - вот почему важно sumбыть int, а не а long. Конечно, как сказал @ace, Java использует целочисленное деление для оценки -1/12, поэтому оно равно нулю.
Дауд говорит восстановить Монику

1
long.MAX_VALUE составляет 9 223 372 036 854 775 807. Это большое, но увеличение всего на 1 миллион раз в секунду приведет вас туда всего за несколько сотен тысяч лет. Вам понадобится всего около 4 миллиардов приращений в секунду, чтобы закончить в течение жизни человека. Здесь мы не говорим о временных масштабах «конца вселенной», если только вы не знаете что-то, чем не делитесь с остальными.
user19057

1
@ user19057 Спасибо за исправление. Вы, конечно, совершенно правы, хотя я бы хотел знать, почему вы думаете, что вселенная просуществует еще более 100 000 лет. В любом случае, я не собираюсь сидеть сложа руки в ожидании завершения моей программы. Там трава для меня, чтобы наблюдать за ростом.
Дауд говорит восстановить Монику

3

Ява

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

Как это устроено:

Java использует кодировку UTF-8 для всего. Я использую truес кириллицей Ye в конце вместо обычного 'e' (благодаря @CodesInChaos), которое static booleanинициализируется как false. Там import ȷava.math.BigDecimal;с точкой без J вместо import java.math.BigDecimal; My ȷava.math.BigDecimalопределяет public static boolean truе = false;и public String toString() { return "-1/12"; }назвать только два очевидных взлома.

Хотел бы я опубликовать это как спойлер, но я не могу понять, как. Вот остальная часть кода, который скрытно скрыт.

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

Erue / true ясно виден, но разница между ȷava и java настолько мала, что мне пришлось несколько раз прочитать комментарий, чтобы заметить эту точку!
Павел Токарц

1
@OldCurmudgeon Я думаю, что в кириллице есть идеальный аналог e : Ye (кириллица)
CodesInChaos

1
Если я не ошибаюсь, вы публикуете неполный код. Если вы импортируете нестандартные пакеты, вы должны также опубликовать их код.
Угорен

1
Кириллическое «е» довольно круто для того, чтобы сделать вещи нечитаемыми. Представьте себе: if (true! = True) {return true} else {return true}; : D
Павел Токарз

1
@ Андрей G правда!
Павел Токарз

2

Нет решений Haskell, неприемлемо!

Мы можем использовать бесконечные списки Хаскелла, чтобы получить точный ответ!

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)

Решение довольно простое, если принять во внимание стрелки ....

Так в чем же подвох?

Нет языкового расширения для определения однострочного комментария


2

С

#include <stdio.h>

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

В соответствии со стандартом C это вполне можно распечатать, Answer = -1/12поскольку будет переполнение целых чисел со знаком, что является неопределенным поведением. Поиск компилятора, который сделает это, оставлен читателю в качестве упражнения.


этот код никогда не достигнетprintf
Bogdacutu

5
Я предпочитаю ответы, которые обычно дают требуемый результат, а не просто «позволяют это».
Паŭло Эберманн

2

Mathematica

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

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

введите описание изображения здесь


2
Не могли бы вы объяснить, что здесь происходит?
ace_HongKongIndependence

Ха-ха, довольно забавно, и это может быть хороший материал, чтобы проверить, понял ли новичок Mathematica основной синтаксис или нет!
xzczd

1

Python 3.x

Вроде новый здесь. Какие-нибудь советы?

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

Как это устроено:

1:

Комментарии к коду (неудивительно) - все ложь, но они отвлекают от основного запутывания.

2:

~ и ^ - это операторы "побитовый не" и "побитовый xor". В результате чего один переопределен до -12.

3:

add установлен на функцию стрелки ECMAScript 6 «(result, counter) => (result + counter, counter)», которая не выполняет то, что предлагают комментарии, - вместо этого она возвращает только последнее выражение «counter» и эффективно нет оп.

4:

Существует две переменные «результата» - одна написана в чистых ASCII-символах (в глобальной области видимости), а другая имеет кириллицу Unicode «ε» (в рамках анонимной функции, используемой для определения add). «result = 1» сбрасывает значение в глобальной области видимости, а вторая строка «result = (0 |! reѕult) / one;» также имеет левую часть, ссылающуюся на переменную «result» в глобальной области видимости, но «результат» в правой части выражения относится к области действия функции и имеет значение 0 (вместо ожидаемого значения 1 ) так что значение! результат / один = -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';
}

Если эти два #defines удалены, код все равно будет действительным кодом C ++ и фактически попытается (но, конечно, потерпит неудачу) вычислить сумму всех целых чисел.

Как это устроено:

Директивы препроцессора превращают основной код в:

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

Помимо объявления Aобъекта, первые три строки - просто запутывание. Последняя строка выполняет всю работу, используя перегруженный оператор <<на Aобъекте.

Учитывая псевдокод постеров, я не удержался, чтобы добавить этот. Он использует ту же самую основную и другую маленькую идею, но я не думаю, что это так элегантно.

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

Как это устроено:

#defineИзменяет значение
while(true) {
для
while(test(counter)) {
на машины , которые безмолвно увлекают каждый раунд суммирования перед переливом добавят 0x80000001 в результате. Следовательно, после увеличения b результат b == получается, когда b четный, и (b + 0x80000000) == результат, когда b нечетный. 1034594986 - целочисленное представление числа с плавающей запятой 1/12. Добавление 0x80000001 к этому приведет к тому, что целое число будет близко к -1/12, и функция теста вернет 0 (false), и цикл завершится.

И почему вы не должны пытаться запустить его:

Если вы хотите увидеть, что работает, предупредите: тестовая функция должна вызываться 2 ^ 32 * 1034594986 раз перед завершением цикла. (т.е. не в вашей жизни). Если вы хотите убедиться, что эта функция работает так, как было сказано, используйте отладчик или измените программу, чтобы увидеть значение результата и b сразу после оператора b ++. Когда они удовлетворены тем, что они равны, когда b равно, просто измените начальное значение b и счетчик на 1034594986. Затем программа должна вывести -0.08333 через некоторое время.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.