โปรแกรมที่เพิ่มจำนวนธรรมชาติทั้งหมดและให้ผลตอบแทน -1/12 [ปิด]


53

ในขณะที่คุณอาจจะรู้ว่ามีความสนุกสนานความเป็นจริงทางคณิตศาสตร์ที่ถ้าคุณเพิ่มทั้งหมดจำนวนธรรมชาติคุณท้ายด้วย ... -1/12 (ดูวิกิพีเดียที่นี่)

แน่นอนว่านี่เป็นผลลัพธ์ที่แปลกมากและไม่สามารถรับได้โดยการเพิ่มหมายเลขหนึ่งตามด้วยหมายเลขอื่น แต่มีเทคนิคทางคณิตศาสตร์พิเศษบางอย่าง

อย่างไรก็ตามงานของคุณคือการเขียนโปรแกรมซึ่งดูเหมือนว่ามันจะพยายามเพิ่มจำนวนธรรมชาติทั้งหมด แต่เมื่อคุณเรียกใช้มันจะส่งกลับ -1/12

ใน pseudocode อาจมีลักษณะเช่นนี้:

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

คุณสามารถทำสิ่งนี้ได้ทุกอย่างที่ต้องการ - คุณสามารถใช้ประโยชน์จากบัฟเฟอร์ล้นบางส่วนเล่นโดยมีข้อผิดพลาดเกิดขึ้นในขณะที่ตัวแปรบางตัวใหญ่เกินไปหรือซ่อนสิ่งสำคัญไว้ในโค้ดด้วยวิธีที่ชาญฉลาด เงื่อนไขเพียงอย่างเดียวคือรหัสนั้นในตอนแรกควรดูราวกับว่ามันพยายามที่จะเพิ่มจำนวนธรรมชาติทั้งหมดและเมื่อรันมันจะส่งกลับ -1-12 (ในรูปแบบใด ๆ มันอาจจะเป็นทศนิยม, ไบนารี, ข้อความ, ASCII ศิลปะสิ่งที่)

แน่นอนว่ารหัสสามารถมีได้มากกว่าที่แสดงด้านบน แต่ควรชัดเจนพอที่จะหลอกผู้อ่าน

นี่คือการประกวดความนิยม - โหวตไอเดียที่ฉลาดที่สุด!


2
แก้ไขแท็กของคุณ: หากเป็นการประกวดความนิยมมันไม่สามารถเป็นโค้ดกอล์ฟได้และเรามีแท็กที่แฝงอยู่สำหรับความท้าทายเช่น "เขียนโค้ดที่ดูเหมือน x แต่ทำ y" อย่างไรก็ตามนี่เป็นความท้าทายที่เหมาะสมสำหรับผู้มาใหม่! :)
Martin Ender

2
@ m.buettner - ขอบคุณสำหรับการแก้ไขแท็กใช่ฉันใหม่ที่นี่ดังนั้นฉันจึงไม่ทราบแท็กทั้งหมด ฉันจะพยายามทำตามกฎ!
Paweł Tokarz

3
ทำไมคำตอบทั้งหมดพร้อมกับคำถามจึงถูกลดระดับลง Downvoter: โปรดแสดงความคิดเห็น
arshajii

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 ซึ่งมีฐานเป็นตัวแทนเช่นเดียวกับ -0.082638867199420928955078125 เมื่อตีความว่าเป็นแทนfloat โปรดทราบว่าจะใช้แทนเพื่อหลีกเลี่ยงการออกจากลูปเมื่อผลรวมถึง 2139135936 (NaN ใน) (ขอบคุณ @CodesInChaos สำหรับการแนะนำแนวคิดนี้แทนการตรวจสอบอิสระ)unsigned int

!(abs<=0.001)abs>0.001floatisNaN

ขอขอบคุณเป็นพิเศษกับ @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หลอกลวงเดียวกันแต่ด้วยตัวดำเนินการ--> "มีแนวโน้มที่จะ"ที่นี่ เนื่องจากทุกหมายเลขมีขนาดเล็กกว่าอินฟินิตี้วงจึงไม่ถูกเรียกใช้แม้แต่ครั้งเดียว

หลังจากแปลงเป็นfloatมันจะถูกเปรียบเทียบกับintจำนวนมายากล (เช่น -0.83333 เปรียบเทียบกับ0xBDAAAAABหรือ 3182078635) ซึ่งแน่นอนแตกต่างกัน


3
สร้าง #define INFINITY ที่ด้านบนและแทนที่ i <INFINITY
ojblass

2
ควรพิจารณาวิธีที่น่าสนใจเพื่อออกไปจากวง
ojblass

สำหรับสิ่งที่คุ้มค่าในฐานสิบหก79776คือซึ่งเป็น137A0 ((int) "\rz") << 4แต่ไม่แน่ใจว่ามีประโยชน์เพียงใด
durron597

3
คุณสามารถกำหนด epsilon เพื่อแยกวง คำอธิบาย: "เนื่องจากเราไม่สามารถวิ่งไปหาอนันต์ได้เราจะแตกออกเมื่อมันมาบรรจบกันในวันที่ 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

มาติกา

\: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 มีแนวโน้มว่าจะเกิดอะไรขึ้น)


สิ่งที่เกิดขึ้นที่นี่เป็นที่ที่เรากำลังตั้งค่าเริ่มต้นregularizationของSumที่จะเป็นกู Dirichlet (เข้ารหัสในบรรทัดแรก - ทราบว่า Mathematica ช่วยให้ตัวอักษร Unicode ในแหล่งที่มา) ดังนั้นบรรทัดที่สองซึ่งออกจากบริบทดูเหมือนว่ามันจะผลิต -1/12อินฟินิตี้จบลงด้วยการผลิตค่า


3
ฉันค่อนข้างมั่นใจว่านี่เป็นการโกงเพราะคุณบอกให้ Mathematica ใช้การทำให้เป็นมาตรฐานที่จำเป็นเพื่อให้ได้ผลรวม
Kyle Kanos

4
@KyleKanos ทำไมการโกงนั้น
arshajii

2
ฉันรู้ว่ามันไม่ใช่รหัสกอล์ฟ แต่เป็นเคล็ดลับ: คุณสามารถตัดอักขระสี่ตัวและเพิ่มได้โดยตรง68+{0,37,46,37,31,36,40,33,48}เนื่องจากPlusมีListableแอตทริบิวต์ โดยส่วนตัวแล้วฉันพบว่ามันสำนวนมากขึ้น
เดวิดจาง

3
@arshjii: มันโกงเพราะคุณควรจะซ่อนความจริงที่ว่ารหัสนั้นทำให้เข้าใจผิด การใช้แพ็คเกจที่เรียกว่า 'การทำให้เป็นมาตรฐาน' ไม่ได้ซ่อนสิ่งนี้ไว้เลย -1 จากฉัน
Kyle Kanos

1
@arshajii: มันซ่อนมากกว่า & ฉันได้ยกเลิกการลงคะแนนแล้ว
Kyle Kanos

10

C

อย่างรูปแบบคำตอบที่เป็นไม่ได้-1/120.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
เมื่อตีความว่าเป็นสตริงบนแพลตฟอร์ม endian เล็ก ๆ น้อย ๆ คุณจะได้รับ -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(มีความสุขในวันนี้? + .- - .+ + .+ กรุณาลงคะแนนฉันขึ้นมา.) สี่เหล่านี้.มีไว้สำหรับการส่งออก
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 ก่อนที่ฉันจะเพิ่มค่าตัวแปรฉันเริ่มต้นตัวจัดการข้อยกเว้น


เพิ่มความคิดเห็น!
Navin

3
เขายังคงรวมกันจนกว่าฉันจะกลายเป็นศูนย์อีกครั้งเนื่องจากล้นที่จุดที่average=sum/i;ให้ SIGFPE ติดโดยhandlerการพิมพ์ -1/12
tomsmeding

ไม่ได้เพิ่มความคิดเห็นต่อจิตวิญญาณของการใช้เล่ห์เหลี่ยม?
ojblass

1
@ojblass ขึ้นอยู่กับความคิดเห็นที่แฝงอยู่ ;-)
Daniel Wagner

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

ฮ่าฮ่าฉันกำลังคิดที่จะโพสต์การสรุปที่เรียบง่ายและอ้างว่ามันใช้งานได้ แต่คุณต้องรอเวลาที่ไม่มีที่สิ้นสุดก่อนที่มันจะพิมพ์ออกมา ดีใจที่ได้เห็นคนอื่นคิดเช่นกัน
Kyle Kanos

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 Platform และ Version มันขึ้นอยู่กับค่าคงที่อื่น ๆ


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
Joshua

8
ธงคอมไพเลอร์ของคุณมอบทุกอย่าง ...
ace_HongKongIndependence

3
“ ช่องโหว่” มาตรฐานที่ไม่ตลกอีกต่อไป - ??/เคล็ดลับ Trigraph มีความยาวตั้งแต่หยุดนิ่ง :(
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

@ PawełTokarzฉันไม่ใช่ผู้เชี่ยวชาญเกี่ยวกับ Java ดังนั้นฉันจึงไม่สามารถบอกได้อย่างแน่นอน แต่มันก็คุ้มค่าที่จะสังเกตว่าเนื่องจาก Java ใช้การแบ่งจำนวนเต็ม-1/12เป็นศูนย์แบบไม่มีเงื่อนไข ดังนั้นฉันคิดว่ามันเป็นพฤติกรรมล้นบางอย่างที่ทำให้ลูปสิ้นสุดและบังเอิญsumล้นไปเป็นศูนย์?
ace_HongKongIndependence

longใช่ล้นจะทำให้หยุดห่วงเมื่อได้รับสูงสุด จักรวาลอาจจะไม่มีอยู่อีกต่อไป แต่นี่เป็นเพียงทฤษฎีใช่ไหม? และใช่ด้านล่าง 32 บิตของsumทั้งหมดจะเป็นศูนย์ - ซึ่งเป็นเหตุผลที่มันเป็นสิ่งสำคัญสำหรับการsumที่จะเป็นไม่ได้int longแน่นอนตามที่ @ace ได้กล่าวไว้ Java ใช้การหารจำนวนเต็มเพื่อประเมิน-1/12ดังนั้นมันจึงเป็นศูนย์
Dawood ibn Kareem

1
ความยาว MAX_VALUE คือ 9,223,372,036,854,775,807 มันใหญ่ แต่การเพิ่มขึ้นเพียง 1 ล้านครั้งต่อวินาทีจะช่วยให้คุณไปถึงที่นั่นในเวลาไม่กี่แสนปี คุณต้องการเพียงเพิ่มขึ้น 4 พันล้านต่อวินาทีเพื่อให้เสร็จภายในอายุการใช้งานของมนุษย์ เราไม่ได้พูดถึง "จุดจบของจักรวาล" ครั้งที่นี่เว้นแต่คุณจะรู้ว่าคุณไม่ได้แบ่งปันอะไรกับพวกเราที่เหลือ
user19057

1
@ user19057 ขอบคุณสำหรับการแก้ไข คุณค่อนข้างถูกต้องถึงแม้ว่าฉันจะชอบที่จะรู้ว่าทำไมคุณคิดว่าจักรวาลจะมีอายุมากกว่า 100 000 ปี ไม่ว่าในกรณีใดฉันจะไม่นั่งรอให้โปรแกรมทำงานเสร็จ มีหญ้าสำหรับฉันที่จะดูการเจริญเติบโต
Dawood ibn Kareem

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еกับซีริลลิเยที่สิ้นสุดแทน 'e' ปกติ (ขอบคุณ @CodesInChaos) ซึ่งเป็นที่static booleaninitialised falseไป มีimport ȷava.math.BigDecimal;กับj ที่ไม่มีจุดแทนคำจำกัดความ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;
    }
}

uerue / true นั้นชัดเจน แต่ความแตกต่างระหว่างȷavaและ java นั้นเล็กมากฉันต้องอ่านความคิดเห็นสองสามครั้งเพื่อหาจุดนี้!
Paweł Tokarz

1
@ OldCurmudgeon ฉันคิดว่ามันมีลักษณะคล้ายตัวอักษรที่สมบูรณ์แบบสำหรับeในอักษรซีริลลิก: Ye (Cyrillic)
CodesInChaos

1
ถ้าฉันไม่ผิดคุณโพสต์รหัสไม่สมบูรณ์ หากคุณนำเข้าแพ็คเกจที่ไม่ได้มาตรฐานคุณควรโพสต์รหัสของพวกเขาด้วย
ugoren

1
Cyryllic 'e' ค่อนข้างเจ๋งที่ทำให้สิ่งต่าง ๆ ไม่สามารถอ่านได้ ลองนึกภาพ: ถ้า (จริง! = จริง) {กลับจริง} อื่น {คืนจริง}; : D
Paweł Tokarz

1
@Andrew G จริง!
Paweł Tokarz

2

ไม่มีโซลูชันของ Haskell ที่ยอมรับไม่ได้!

เราสามารถใช้รายการไม่สิ้นสุดของ 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
ฉันชอบคำตอบที่มักจะสร้างผลลัพธ์ที่ต้องการไม่ใช่แค่ "อนุญาต"
Paŭlo Ebermann

2

มาติกา

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

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

ป้อนคำอธิบายรูปภาพที่นี่


2
คุณจะให้คำอธิบายเกี่ยวกับสิ่งที่เกิดขึ้นที่นี่หรือไม่?
ace_HongKongIndependence

ฮ่าฮ่าตลกมากและมันอาจเป็นวัสดุที่ดีในการทดสอบว่าMathematica newbie เข้าใจไวยากรณ์พื้นฐานหรือไม่!
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:

~ และ ^ เป็นตัวดำเนินการ "bitwise not" และ "bitwise xor" ส่งผลให้หนึ่งถูกนิยามใหม่เป็น -12

3:

เพิ่มถูกตั้งค่าเป็นฟังก์ชันลูกศร ECMAScript 6 "(ผลลัพธ์ตัวนับ) => (ผลลัพธ์ + ตัวนับตัวนับ)" ซึ่งไม่ได้ทำตามความคิดเห็นที่แนะนำ - แทนที่จะส่งกลับเฉพาะนิพจน์สุดท้าย "ตัวนับ" เท่านั้นและมีประสิทธิภาพ ไม่มี op

4:

มีตัวแปร "ผลลัพธ์" สองตัว - หนึ่งตัวถูกเขียนด้วยอักขระ ASCII แท้ๆ (ในขอบเขตทั่วโลก) และอีกตัวหนึ่งมี Unicode Cyrillic "ѕ" (ภายในขอบเขตของฟังก์ชันที่ไม่ระบุตัวตนที่ใช้กำหนดนิยาม) "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';
}

หากทั้งสอง#defineถูกลบออกรหัสจะยังคงเป็นรหัส C ++ ที่ถูกต้องและลอง (แต่แน่นอนล้มเหลว) ในการคำนวณผลรวมของจำนวนเต็มทั้งหมด

มันทำงานอย่างไร:

คำสั่ง preprocessor เปลี่ยนรหัสหลักเป็น:

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

นอกเหนือจากการประกาศAวัตถุสามบรรทัดแรกนั้นเป็นเพียงการทำให้งงงวย บรรทัดสุดท้ายทำงานทั้งหมดโดยใช้โอเปอเรเตอร์ที่โอเวอร์โหลด<<บนAวัตถุ

ให้ pseudocode ผู้โพสต์ฉันไม่สามารถต้านทานการเพิ่มอันนี้ มันใช้ความคิดพื้นฐานแบบเดียวกันและความคิดเล็ก ๆ น้อย ๆ แต่ฉันไม่คิดว่ามันจะสง่างาม

#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 (เท็จ) และลูปจะสิ้นสุดลง

และทำไมคุณไม่ควรลองเปิดใช้งาน:

หากคุณต้องการที่จะเห็นว่างานได้รับการเตือน: การทดสอบ funtion ต้องเรียกว่า 2 ^ 32 * 1034594986 ครั้งก่อนที่จะยุติการวนซ้ำ (เช่นไม่ได้อยู่ในชีวิตของคุณ) หากคุณต้องการตรวจสอบว่าฟังก์ชั่นนั้นเป็นไปตามที่บอกหรือไม่ให้ใช้ดีบักเกอร์หรือเปลี่ยนโปรแกรมเพื่อดูค่าผลลัพธ์และ b หลังคำสั่ง b ++ เมื่อพอใจว่าพวกเขามีค่าเท่ากันเมื่อ b เป็นเพียงแค่เปลี่ยนค่าเริ่มต้นของ b และตัวนับเป็น 1034594986 โปรแกรมควรออก -0.08333 หลังจากนั้นสักครู่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.