すべての自然数を加算して-1/12を生成するプログラム[終了]


53

ご存知かもしれませんが、すべての自然数を加算すると、... -1/12 (Wikipediaを参照)という数学的な楽しみがあります。

もちろん、これは非常に奇妙な結果であり、1つの数値に続けて別の数値を追加することでは得られませんが、いくつかの特別な数学的なトリックです。

しかし、あなたの仕事は、すべての自然数を追加しようとするよう見えるプログラムを書くことですが、それを実行すると、-1 / 12を返します。

擬似コードでは、次のようになります。

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

好きな方法でこれを行うことができます。バッファオーバーフローを利用したり、変数が大きくなりすぎたときにエラーをスローしたり、コードに沿って重要なことを巧妙に隠したりできます。唯一の条件は、コードが最初にすべての自然数を追加しようとしているかのように見え、実行時に-1/12を返すことです(任意の形式で、10進数、バイナリ、テキスト、ASCIIアートなど)。

もちろん、上記のコードよりもはるかに多くのコードを含めることができますが、読者を欺くには十分に明確でなければなりません。

これは人気コンテストです-最も賢いアイデアに投票してください!


2
タグを修正しました。人気コンテストの場合、コードゴルフはできません。また、「xのように見えるがyを実行するコードを作成する」などの課題のための手に負えないタグがあります。とにかく、これは新参者にとってかなりまともな挑戦です!:)
マーティンエンダー

2
@ m.buettner-タグを編集してくれてありがとう、はい、私はここに新しいので、すべてのタグを認識していません。ルールに従うようにしよう!
パウェウトカルツ

3
質問と一緒にすべての答えがちょうど投票されたのはなぜですか?Downvoter:コメントを残してください。
アルシャジー

7
最初の行は、あなたの解釈によっては、完全に真実ではありませんmath.stackexchange.com/questions/39802/...
QWR

3
このサイトでは、手に負えない課題がトピックではなくなったため、この質問をトピック外として終了することに投票しています。meta.codegolf.stackexchange.com/a/8326/20469
cat

回答:


38

C

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であり、のfloat代わりにとして解釈される場合、-0.082638867199420928955078125と同じバイナリ表現を持ちunsigned intます。

メモ!(abs<=0.001)代わりに使用されるabs>0.001合計が2139135936(NaNの中に到達したときに、ループを終了避けるためfloat)。(独立したisNaNチェックの代わりにこのアイデアを提案してくれた@CodesInChaosに感謝します。)

カウンターの代わりに合計を比較することでループを終了するというアイデアを提供してくれた@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-to- floatトリックを使用しますが、ここでは--> tends to」演算子を使用します。すべての数値は無限大よりも小さいため、ループは一度も実行されません。

変換後floatintマジック番号と比較されます(つまり、-0.83333は0xBDAAAAAB、または3182078635 と比較されます)。これはもちろん異なります。


3
上部で#define INFINITYを作成し、i <INFINITY
ojblass

2
ループから抜け出す興味深い方法を検討する必要があります。
ojblass

価値があるのは、16進数79776137A0であり、です((int) "\rz") << 4。けれども、わからないどのように有用である
durron597

3
イプシロンを定義して、ループから抜け出すことができます。説明:「無限に走ることはできないので、浮動小数点の誤差範囲内で-1/12に収束したら、ブレークアウトします」または同様のことです。繰り返しごとにフロート値をチェックする必要がありますが、その奇数の「無限大」値は取り除かれます。
ジオビット

1
最初のコードでは、NaNチェックを削除するwhile(!(abs<delta))代わりに使用できますwhile(abs>delta)
CodesInChaos

20

Python

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

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

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

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

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

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

  # return average of partial sums
  return t_sum / stop

# All natural numbers
n = count(1)

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

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

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

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

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

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

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

結果:

-0.0833333333333

だから、トリックは何ですか?

秘isは、これが有効な計算であるということです。


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}ので、4文字をカットして直接追加することができます。個人的には、これがより慣用的だと思います。PlusListable
デビッドチャン

3
@arshjii:コードが誤解を招くという事実を隠すことになっているため、不正行為です。「正規化」と呼ばれるパッケージを使用しても、これはまったく隠されません。私から-1。
カイルカノス

1
@arshajii:それはもう少し隠しますが、私はそれを否定しませんでした。
カイルカノス

10

C

答えを-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;
}

使い方?

386106を除く656618までのすべての数値を合計します。これは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 == 2568ビットのセルサイズを想定して、オーバーフローが発生するまで。その時点で、にiなり0、ループが終了し、次のコメントが実行されます。


これは意味がありません。ほとんどのインタープリターは、あなたがそれを評価1 + 2 + 3 + ...すると主張するという事実だけでなく、256 もあなたが主張するように三角形でなければならないことを意味しi == 256ますが、256は三角形の数ではありません。また、コードはどこに出力され-1/12ますか?
ティムテック

@Timtechループは終了します。オーバーフローしているのは合計ではなく、カウンターです。小さな問題が1つあります:(今日1/12-1/12幸せですか?+ .-- .+ + .+投票してください.)これら4つ.は出力用です。
ace_HongKongIndependence

それはカウンターだった場合、2つの選択肢があるでしょう@ace:1)細胞はラップを行う場合は、オーバーフローはないだろうOR 2)細胞がラップしていない場合、カウンタも近づい前に、その合計が道をオーバーフローします256
ティムテック

@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
彼は、オーバーフローのためにiが再びゼロになるまで加算を続けますが、その時点average=sum/i;でSIGFPEが得られhandlerます。
tomsmeding

弱者の精神に反するコメントを追加していませんか?
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

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

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;

}

合理的な時間で(ほぼ)無限の合計を処理するには、コンパイラーの最適化のために次のオプションを使用してコンパイルします(必須)。

$ gcc -trigraphs sum.c

サンプル出力:

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

1
これがどのように機能するかを知りたい場合は、.Sファイルを読んでください。
ジョシュア

8
あなたのコンパイラフラグは...離れてすべてを提供します
ace_HongKongIndependence

3
もはやおかしくない標準の「抜け穴」 - ??/トライグラフのトリックは、賢くなくなってから長い間あります。:(
doppelgreener

リンクをありがとう、それは多くを説明します。FAQへのリンクはどこかにありますか、それとも毎回検索する必要がありますか?

@tolosこれをお気に入りにするか、[ faq ]メタタグの下にある唯一の質問の1つであるか、コミュニティ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私はJavaの専門家ではないので、はっきりとは言えませんが、Javaが整数除算を使用しているの-1/12は事実上ゼロです。だから、ループが終了し、偶然sumにゼロにオーバーフローするのは、ある種のオーバーフロー動作だと思いますか?
ace_HongKongIndependence

オーバーフローは、ループが最大値に達したときにループを停止しlongます。宇宙はおそらくそれまでにもう存在しないでしょうが、これは単なる理論ですよね?そして、はい、の下位32ビットsumはすべてゼロになります。sumそのためint、でなくであることが重要ですlong。もちろん、@ aceが言ったように、Javaは整数除算を使用して評価-1/12するため、ゼロになります。
Dawoodは、モニカを

1
long.MAX_VALUEは9,223,372,036,854,775,807です。それは大きいですが、1秒あたりわずか100万回インクリメントするだけで、ほんの数十万年でそこに到達できます。人間の寿命内で終了するのに必要なのは、1秒あたり約40億の増分だけです。ここでは、他の人と共有していない何かを知っていない限り、「宇宙の終わり」のタイムスケールについて話しているわけではありません。
user19057

1
@ user19057修正していただきありがとうございます。もちろん、あなたはまったく正しいのですが、なぜ宇宙があと10万年以上続くと思うのか知りたいです。いずれにせよ、プログラムの実行が完了するのを待つつもりはありません。成長を見守る草があります。
ダウードはモニカ回復言う

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コーディングを使用します。に初期化された通常の 'e'(@CodesInChaosのおかげ)の代わりに、最後にキリル文字Yeを使用truеします。ありますとドットなしjの代わりに 私の定義と名前が、2つの明白なハックへ。static booleanfalseimport ȷava.math.BigDecimal;import java.math.BigDecimal;ȷava.math.BigDecimalpublic 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の違いは非常に小さいため、この点を見つけるためにコメントを数回読む必要がありました。
パウェウトカルツ

1
私はのための完璧なそっくりがあると思い@OldCurmudgeon E:キリル文字でイェ(キリル)
CodesInChaos

1
間違っていない場合は、不完全なコードを投稿します。非標準パッケージをインポートする場合は、それらのコードも投稿する必要があります。
ウゴレン

1
cyryllic 'e'は、物を読めないようにするのに非常にクールです。想像してみてください:if(true!= true){return true} else {return true}; :D
パウェウトカルツ

1
@Andrew 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

C

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

「結果」変数は2つあります。1つは純粋なASCII文字(グローバルスコープ内)で記述され、もう1つはUnicodeキリル文字「ѕ」(addの定義に使用される匿名関数のスコープ内)です。「result = 1」はグローバルスコープ内の値をリセットし、2行目は「result =(0 |!reѕult)/ one;」を返します。また、左側はグローバルスコープの「結果」変数を参照しますが、式の右側の「結果」は関数のスコープを参照し、値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';
}

2つ#defineが削除されても、コードは有効なC ++コードのままであり、実際にすべての整数の合計を計算しようとします(もちろん失敗します)。

使い方:

プリプロセッサディレクティブは、メインコードを次のように変換

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

Aます。オブジェクトの宣言を除けば、最初の3行は難読化にすぎません。最後の行は<<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は、 オーバーフローが結果に0x80000001を追加する前に、合計の各ラウンドを静かにオーバーフロー
while(true) {
する
while(test(counter)) {
Onマシンの意味を変更します。したがって、bの増分後、bが偶数の場合はb ==結果、bが奇数の場合は(b + 0x80000000)==結果となります。1034594986は、浮動小数点数1/12の整数表現です。これに0x80000001を追加すると、整数は-1/12に近くなり、テスト関数は0(false)を返し、ループは終了します。

そして、なぜあなたはそれを実行しようとするべきではありません:

動作を警告する場合は、ループを終了する前に2 ^ 32 * 1034594986回テスト関数を呼び出す必要があります。(つまり、あなたの生涯ではない)。関数が指示どおりに動作することを確認する場合は、デバッガを使用するか、プログラムを変更して、b ++ステートメントの直後にあるresultとbの値を確認します。bが等しい場合に等しいと判断されたら、bの初期値を変更して1034594986にカウンターします。その後、プログラムはしばらくして-0.08333を出力するはずです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.