Програма, яка додає всі натуральні числа та врожаї -1/12 [закрито]


53

Як ви могли знати, є математична забава - факт, якщо додати всі натуральні числа, ви закінчите ... -1/12 (див. Вікіпедію тут) .

Звичайно, це дуже дивний результат, і його неможливо отримати, просто додавши одне число, а за іншим - деякі спеціальні математичні хитрощі.

Однак ваше завдання - написати програму, схожу на те , що вона намагається додати всі натуральні числа, але коли ви запускаєте її, вона повертається -1/12.

У псевдокоді це може виглядати приблизно так:

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

Це можна зробити будь-яким способом - вам можна скористатися деяким переповненням буфера, грати з помилками, викинутими, коли якась змінна стає занадто великою або просто приховати вирішальну річ за кодом якось розумним чином. Єдиною умовою є те, що код спочатку повинен виглядати так, ніби він намагається додати всі натуральні числа, а під час запуску він повертає -1/12 (у будь-якому форматі це може бути десятковий, двійковий, текстовий і будь-який інший текст).

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

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


2
Виправлені ваші теги: якщо це популярність-конкурс, це не може бути код-гольф, і у нас є непомітний тег для таких проблем, як "написати код, який виглядає як x, але так". У будь-якому випадку, це є досить гідним завданням для новачка! :)
Мартін Ендер

2
@ m.buettner - дякую за редагування тегів, так, я тут новачок, тому мені не відомі всі теги. Я спробую дотримуватися правил!
Paweł Tokarz

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замість an unsigned int.

Зауважте, що !(abs<=0.001)використовується замість того, abs>0.001щоб уникнути припинення циклу, коли сума досягне 2139135936 (NaN в 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-TOTrick float, але тут --> оператор "прагне" . Оскільки кожне число менше, ніж нескінченність, цикл не буде виконаний жодного разу.

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


3
зробіть #define INFINITY вгорі і замініть i <INFINITY
ojblass

2
Слід розглянути цікаві способи виходу з петлі.
ojblass

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

3
Ви можете визначити епсилон для виходу з циклу. Пояснення: "оскільки ми не можемо бігти до нескінченності, ми вирвемося, як тільки він сходиться на -1/12 в межах помилки з плаваючою комою" або подібного. Вам доведеться перевіряти значення float кожної ітерації, але вона позбудеться цього дивного значення "нескінченності".
Геобіць

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

Математика

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

Брейнфук

+ [ [->+>+<<] > [-<+>] <+ ]
--------------------------------------------------------------------------------
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(Щасливий сьогодні? + .- - .+ + .+ Будь ласка, проголосуйте мене .) Ці чотири .- для виведення.
ace_HongKongIndependence

@ace Якби це був лічильник, було б два варіанти: 1) Якщо комірки завернуть, то не було б переливу АБО 2), якщо комірки не загортаються, то сума переповнюватиметься ще до того, як лічильник навіть наблизився 256.
Timtech

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

1
@Timtech Cells роблять обгортання, тому 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.
tomsmeding

не додає коментарів проти духу недоторканості?
ojblass

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

8
unsigned int sum=3182065200L; printf("%.3f\n",*(float*) &sum);це мертвий подарунок, що щось там відбувається, і бачачи, що це в обробці для SIGFPE, це робить занадто очевидним для моїх смаків.
hvd

4

Перл 6

Це обчислює суму за допомогою функції zeta. Я б використав [+] 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

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

Це додає всі числа від 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 ] або знайти його через FAQ FAQ .
doppelgreener

3

Java

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

Теоретично це буде надруковано true. Однак я думаю, що мій комп'ютер розсиплеться в пил, перш ніж він закінчить його працювати.


1
Чому це повинно бути справжнім? Чому ви очікуєте, що сума досягне -1/12?
Paweł Tokarz

@ PawełTokarz Я не експерт по Java, тому не можу сказати напевно, але варто зазначити, що оскільки Java використовує цілочисельний поділ -1/12, фактично дорівнює нулю. Тож я припускаю, що це якась поведінка переповнення, яка призводить до того, що цикл закінчується і випадково sumпереповнює нуль?
ace_HongKongIndependence

Так, переповнення зробить цикл припиненням, коли він досягне максимуму long. Всесвіт, мабуть, вже не існуватиме до цього часу, але це просто теоретично, правда? І так, останні 32 біти sumволі будуть нульовими - саме тому важливо sumбути an int, а не a long. Звичайно, як сказав @ace, Java використовує ціле ділення для оцінки -1/12, тому це нуль.
Dawood ibn Kareem

1
long.MAX_VALUE - 9,223,372,036,854,775,807. Це велике, але збільшення лише 1 мільйон разів на секунду привезе вас туди всього за кілька сотень тисяч років. Вам знадобиться лише близько 4 мільярдів приростів за секунду, щоб закінчити протягом життя людини. Тут ми не говоримо про часові шкали "кінця Всесвіту", якщо ви не знаєте чогось, чим не ділитеся з рештою з нас.
user19057

1
@ user19057 Дякуємо за виправлення Ви, безумовно, маєте рацію, хоча мені б хотілося знати, чому ви думаєте, що Всесвіт проіснує більше 100 000 років. У будь-якому випадку, я не збираюся сидіти навколо, чекаючи, коли моя програма закінчить працювати. Там мені трава спостерігати, як росте.
Давуд ібн Карім

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

Як це працює:

Java використовує кодування UTF-8 для всього. Я використовую truез кирилицею Ye на кінці замість звичайного «е» (завдяки @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;
    }
}

Ŧrue / true добре видно, але різниця між ȷava та java настільки мала, що мені довелося прочитати коментар кілька разів, щоб помітити цю крапку!
Paweł Tokarz

1
@OldCurmudgeon Я думаю, що в кириличному алфавіті є ідеальний елемент для e :
ки

1
Якщо я не помиляюся, ви надсилаєте неповний код. Якщо ви імпортуєте нестандартні пакети, ви також повинні розмістити їх код.
угорен

1
Кириличне "е" - це дуже круто, що робить речі нечитабельними. Уявіть собі: якщо (правда! = Правда) {повернути правду} ще {повернути істину}; : D
Paweł Tokarz

1
@Andrew G правда!
Paweł Tokarz

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
Я віддаю перевагу відповідям, які зазвичай дають необхідний вихід, а не просто "дозволяють".
Paŭlo Ebermann

2

Математика

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:

функція "додавання" встановлена ​​в функції стрілки ECMAScript 6 "(результат, лічильник) => (результат + лічильник, лічильник)", яка не робить те, що в коментарях пропонується, а замість цього повертає лише останній вираз "лічильник" і ефективно не-оп.

4:

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

Якщо два #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.