Classic Proof Fallacy [ปิด]


18

พื้นหลัง

ดังนั้นเราทุกคนรู้หลักฐานคลาสสิกที่เป็นเช่นนี้:

A = ข
รฒร = AB
รฒร - b² = AB - b²
(AB) (A + B) = b (AB)
(A + B) = b
B + B = b
2b = b
2 = 1 (ฮ่า!)
ของ แน่นอนว่าข้อผิดพลาดคือคุณไม่สามารถหารด้วย 0 ได้เนื่องจาก a = b, a - b = 0 ดังนั้นจึงมีการหารที่ซ่อนอยู่ 0

ความท้าทาย

คุณต้องทำซ้ำหลักฐานนี้ ก่อนอื่นให้ประกาศจำนวนเต็มสองตัว a และ b (ไม่สำคัญว่าคุณจะเรียกมันว่าอะไร) นั่นเท่ากับ จากนั้นประกาศ aMod และ bMod ให้เป็นเวอร์ชันที่แก้ไขได้ของ a และ b และเริ่มต้นเท่ากับ a และ b ตามลำดับ คุณต้องคูณทั้งสองด้วย a แล้วลบ b * b จากทั้งคู่ จากนั้นคุณต้องหารด้วย a - b แล้วหารด้วย a (b) เพื่อให้ได้ จากนั้นพิมพ์ aMod และ bMod ด้วยเครื่องหมายเท่ากับระหว่างพวกเขา

คนเล่ห์เหลี่ยม

แน่นอนเนื่องจากคุณประกาศ a และ b ให้เท่ากับ a - b = 0 และการหารด้วย 0 ทำให้เกิดข้อผิดพลาด ดังนั้นคุณต้องปลอมอย่างสร้างสรรค์ นอกจากนี้เนื่องจากคุณกำลังพยายามทำซ้ำการพิสูจน์ผลลัพธ์บนการดำเนินการทั้งหมดบน aMod และ bMod ต้องไม่เท่ากันเมื่อพิมพ์ พวกเขาไม่ต้องเท่ากับ 2 และ 1 เพียงแค่ตัวเลขสองตัวที่ไม่เท่ากัน

นี่คือตัวอย่าง:

#include <iostream>
#define subtract(a, b) a - b

using namespace std;
int main()
{
    int a = 4, b = 4;
    int a_2 = a, b_2 = b;

    a_2 *= a;
    b_2 *= b;

    a_2 -= b * b;
    b_2 -= b * b;

    a_2 = a_2 / subtract(a, b);
    b_2 = b_2 / subtract(-b, -a); // a - b == (-b) - (-a)

    a_2 /= a;
    b_2 /= a;

    cout << a_2 << " = " << b_2 << " because I did the same operations on both of them.";

    return 0;
}

อาจไม่ใช่สิ่งที่ดีที่สุด แต่มันแสดงให้เห็นถึงประเด็น

โบนัสเล่ห์เหลี่ยม

แทนการพิมพ์เครื่องหมายเท่ากับคุณสามารถพิมพ์ออกมาเพียงสองตัวแปร (aMod และ BMOD) แล้วมีรหัสที่ปรากฏเพื่อเปรียบเทียบตัวแปรทั้งสองเพื่อความเท่าเทียมกัน แต่ในความเป็นจริงการโกหกว่าพวกเขาเท่ากับ (และพิมพ์แบบฟอร์มของบางส่วนtrue)

โปรดจำไว้ว่านี่คือการประกวดความนิยมดังนั้นจำนวน upvotes สูงสุดจึงชนะ
นอกจากนี้เวอร์ชันใหม่ของคณิตศาสตร์ที่ชื่อว่า Mathematics 2.0 ได้ใช้ช่องโหว่มาตรฐานทำให้การพิสูจน์เป็นโมฆะโดยอัตโนมัติ


นี่คือลิงค์ Wikipedia ของการเข้าใจผิดทางคณิตศาสตร์เพื่อให้ผู้คนสามารถเข้าใจได้ดียิ่งขึ้น

3
ฉันลงคะแนนให้ปิดคำถามนี้เป็นหัวข้อนอกเพราะความท้าทายที่ไม่ได้อยู่ในหัวข้อบนเว็บไซต์นี้อีกต่อไป meta.codegolf.stackexchange.com/a/8326/20469
cat

คำตอบ:


17

JavaScript

var a=3,b=3,a2=3,b2=3
[a2,b2]=[a2*a,b2*a]
[a2,b2]=[a2-b*b,b2-b*b]
[a2,b2]=[a2/(a-b),b2/(a-b)]
console.log([a2/a,b2/a])

เอาท์พุท:

[1, NaN]

โปรดทราบว่า 0/0 = NaN

เปรย

ลองเพิ่มเครื่องหมายอัฒภาค โปรแกรมนี้เป็นจริง
และน่าน var a=3,b=3,a2=3,b2=3[a2,b2]=...=[a2/(a-b),b2/(a-b)];console.log([a2/a,b2/a])
[3/0,undefined/0]/3


ว้าว. นั่นเป็นเรื่องที่ฉลาดมาก "บังเอิญ" ลืมที่จะเพิ่มเซมิโคลอน (เกือบ) ทั้งประโยคในโปรแกรม
user155698

3

Python 2

ฉันค่อนข้างมั่นใจว่ามันชัดเจนเพราะทุกคนรู้จัก Python แต่นี่เป็นความพยายามของฉัน:

a=b=1
x,y=a*a,a*b
x,y=x-b*b,y-b*b
x,y=a+b/a-b,b
x,y=x/a,y/a
print(x==y)

มันออกTrueมา

คำแนะนำ:

ตรวจสอบส่วนของฉัน


เพราะทุกคนใช้งูหลาม ฉันรู้หลาม แต่ฉันไม่ค่อยได้ใช้มัน
rpax

@rpax นั่นคือสิ่งที่ฉันหมายถึง
mbomb007

ขออภัยฉันอ่านคำตอบของคุณไม่ถูกต้อง
rpax

2

ทับทิม

def calculate a,
  b = a
  left, right = a, b
  left, right = [left, right].map { |x| x * a     }
  left, right = [left, right].map { |x| x - b*b   }
  left, right = [left, right].map { |x| x / a - b }
  left, right = [left, right].map { |x| x / b     }
  puts $/=[left, right].join(' = ')
end

calculate 3,
STDOUT.write($/)

ideone

คำแนะนำ:

,

คำอธิบาย:

สองบรรทัดที่ลงท้ายด้วยเครื่องหมายจุลภาคทำให้โปรแกรมทำงานแตกต่างจากที่ทำ หากไม่มีเครื่องหมายจุลภาควิธีใช้อาร์กิวเมนต์เดียวaตั้งbค่าเท่ากับaดำเนินการแปลงจากการพิสูจน์ในแต่ละคน (ยกเว้นเนื่องจากวงเล็บบางส่วนที่ขาดหายไปจะไม่หารด้วย 0) และผลลัพธ์ผลลัพธ์ (ด้วยอินพุต 3 มันจะเอาท์พุท "-1 = -1" อย่างไรก็ตามด้วยเครื่องหมายจุลภาคต่อท้ายb = aบรรทัดกลายเป็นส่วนหนึ่งของลายเซ็นวิธีการซึ่งหมายความว่ามันประกาศอาร์กิวเมนต์ที่สองที่มีค่าเริ่มต้นการอุทธรณ์วิธีการที่ปลายผ่านใน ผลลัพธ์ของSTDOUT.write($/)ซึ่งคือ 1 (จำนวนไบต์ที่เขียนไปยัง STDOUT เนื่องจาก$/ถูกกำหนดไว้ล่วงหน้าให้กับอักขระบรรทัดใหม่) ดังนั้น a คือ 3 และ b คือ 1 ทำให้เกิดสมการเริ่มต้นเป็น "3 = 1" ขยะใน ขยะออก


เคล็ดลับดีที่มีขึ้นบรรทัดใหม่ของคุณ
LegionMammal978

คุณสามารถเพิ่มคำอธิบายสำหรับผู้ที่ไม่ใช่ Rubyists ได้หรือไม่?
kirbyfan64sos

@ kirbyfan64sos แน่นอนแล้ว
เนื้อเยื่อ

2

GolfScript

คำเตือน: โปรแกรมนี้โกงนิดหน่อยเพราะมันไม่ได้พิมพ์ aMod และ bMod

1nt main(){
  int a = 2, b = 2;
  int aMod,bMod;
//The next line should throw and error, but why doesn't it??/
  aMod = (a*a - b*b) / (a-b);
//The next line should throw and error, but why doesn't it??/
  bMod = (b*a - b*b) / (a-b);
//The if should fail, but it works??/
  if(aMod == bMod)
    printf("1");
  return 0;
};

ลองที่นี่ !

แล้วเกิดอะไรขึ้น

สิ่งแรกที่คุณอาจสังเกตเห็นคือ "trigraph ต้องห้าม" แต่จำไว้ว่านี่คือ GolfScript ไม่ใช่ C! นอกจากนี้อาจสังเกตเห็นว่ามันไม่ได้พูดว่า "int main ()" จริง ๆ แล้วมันพูดว่า "1nt main ()" ใน GolfScript คำว่า "1" หมายถึงการกด 1 ลงบนสแต็กและ "nt main" ได้รับการประมวลผลเป็นสองตัวแปรที่ไม่มีการกำหนดค่าเริ่มต้นซึ่งไม่ทำอะไรเลย วงเล็บสองตัวแรกเพิ่ม 1 เข้ากับหมายเลขบนสุดของสแต็กจากนั้นลบออกหนึ่งอัน เครื่องหมายวงเล็บแสดงถึงบล็อกที่ถูกผลักลงบนสแต็กจากนั้นเครื่องหมายอัฒภาคจะปรากฏขึ้นทันที ดังนั้นในตอนท้ายเราเพิ่งมี "1" ดั้งเดิมที่ถูกพุชและเมื่อสิ้นสุดโปรแกรม GolfScript สแต็กจะถูกพิมพ์ คำตอบนี้เป็นแรงบันดาลใจนี้อย่างใดอย่างหนึ่ง


ตรวจพบ Trigraphs เปิดใช้งานระบบ -1 อัตโนมัติ ข้อผิดพลาด: -1 ล้มเหลว (4792, RPLS)
เครื่องคิดเลข

นี่มันลับ ๆ ล่อ ๆ เพราะมันหลอกให้คุณคิดว่ามันหลอกคุณไม่สำเร็จ +1
Rɪᴋᴇʀ

1

อารัมภบท

areEqual(A, B) :-
    Amod = A,
    Bmod = B,

    Amod = Amod * A,
    Bmod = Bmod * B,

    Amod = Amod - B*B,
    Bmod = Bmod - B*B,

    Amod = Amod / (A-B),
    Bmod = Bmod / (A-B),

    Amod = Amod / A,
    Bmod = Bmod / A,

    Amod == Bmod.

เอาต์พุตเมื่อareEqual(4,4)ถูกเรียก (หรือตัวเลขอื่น ๆ สองสามตัวจริง ๆ ):

false

ทำไม?

ใน Prolog ตัวดำเนินการ "=" ไม่มีผลกระทบ มันคือ "การรวมกัน" ดังนั้นจึงAmod = Amod * Aล้มเหลวเนื่องจากAmodมีการรวมเป็นหนึ่งเดียวกันAและไม่สามารถรวมเป็นหนึ่งAmod * Aได้ Prolog จากนั้นหยุดการเรียกใช้กฎปัจจุบันและส่งคืนfalseทันที


2
ฉันคิดว่ามันควรจะเป็นอย่างอื่นคุณต้องเอาท์พุท "จริง" เมื่อทั้งสองค่าแตกต่างกันไม่ใช่ "เท็จ" เมื่อพวกเขามีค่าเท่ากับ ^^ '
Katenkyo

1

JavaScript

//Very badly written code!
//No! It is "poetic" code!
while(true){break;}{ 
let scrollMaxX = 3, screenX = 3;
var scrollBarWithBeerMax = scrollMaxX, Yscroll = screenX; for(var i = 0; i<1; i++){}}

scrollBarWithBeerMax *= scrollMaxX;
Yscroll *= screenX;

scrollBarWithBeerMax -= screenX * screenX;
Yscroll -= screenX * screenX;

scrollBarWithBeerMax /= (scrollMaxX - screenX);
Yscroll /= (scrollMaxX - screenX);

alert(scrollBarWithBeerMax + ' = ' + Yscroll);

ผลลัพธ์:
http://jsbin.com/furino/2/edit?js,output JsBin ดูเหมือนจะไม่สามารถเรียกใช้รหัสนี้ได้ ใช้คอนโซลของเบราว์เซอร์แทน

ทำไม?

scrollMaxX และ screenX เป็นตัวแปรที่มีอยู่แล้ว มันถูกสร้างขึ้นในเบราว์เซอร์ ดังนั้นผลลัพธ์อาจแตกต่างกันไป คำหลักให้เปลี่ยนค่าของพวกเขาชั่วคราว

JavaScript อีกอันหนึ่ง: มันไม่ปฏิบัติตามกฎอย่างแน่นอนมันจะออกเฉพาะในกรณีที่ตัวแปรเท่ากันหรือไม่

var a = 2;
var b = 2;

var a_duplicate = a;
var b_duplicate = b;

a_duplicate*=a
b_duplicate*=b;

a_duplicate-=b*b;
b_duplicate-=b*b;

a_duplicate/=(a-b);
b_duplicate/=(a-b);

alert(a_duplicate==b_duplicate);

ทำไม?

NaN ไม่เท่ากับ NaN ตามข้อมูลจำเพาะลอยตัวของ IEEE ขอบคุณ Alex Van Liew ที่ชี้ให้เห็นว่านี่ไม่ได้ใช้กับ Javascript เท่านั้น


NaNไม่เท่ากับNaNข้อกำหนดลอยของ IEEE ในความเป็นจริงวิธีที่รวดเร็วในการทดสอบว่าคุณมีเครื่องหมายNaNใน C คือการเปรียบเทียบกับตัวเอง ดังนั้นสิ่งนี้ใช้ได้กับทุกภาษาไม่ใช่แค่ JS
Alex Van Liew

1
@AlexVanLiew น่าสนใจ ฉันไม่รู้ว่า! ตกลงเปลี่ยนคำตอบของฉันเล็กน้อยและเพิ่มเครดิตในกรณีที่ถึงกำหนด
Stefnotch

0

Fantom

a := 3
b := 3
duplicates := [a:b]
duplicates = duplicates.map {it * a}
duplicates = duplicates.map {it - b*b}
duplicates = duplicates.map {it / a-b}
echo(duplicates.join("") |Int a_2, Int b_2 ->Str| {"" +  a_2 + " = " + b_2})

เอาท์พุท:

-3 = 3

ทำไม?

[a: b] เป็นแผนที่ไม่ใช่รายการ ไม่ส่อเสียดดังนั้นฉันรู้ว่า :(


คุณน่าจะa เท่ากับ bในตอนท้าย
mbomb007

จุดจบของการเข้าใจผิดดั้งเดิมคือ 2 = 1 ดังนั้นคำตอบสุดท้ายของที่นี่ไม่ควรจะเป็น "ของจริง"
Cain

ฉันคิดถึงโบนัสที่ได้รับ ไม่เป็นไร. "แทนที่จะพิมพ์เครื่องหมายเท่ากับคุณสามารถพิมพ์เพียงสองตัวแปร (aMod และ bMod) แล้วมีรหัสที่ปรากฏขึ้นเพื่อเปรียบเทียบตัวแปรสองตัวเพื่อความเท่าเทียมกัน แต่ในความเป็นจริงแล้วมันอยู่ที่เท่ากัน ."
mbomb007

0

การเข้าใจผิดที่คลาสสิกต้องใช้ความผิดพลาดทางไวยากรณ์คลาสสิก C น่าเศร้าที่ฉันได้พบกับนักพัฒนา "ระดับสูงเท่านั้น" บางคนที่เชื่อว่า C เสียเนื่องจากผลลัพธ์คล้ายกับรหัสนี้ หากคุณรู้วิธีการทำงานของ C มันจะค่อนข้างชัดเจน แต่ถ้าคุณเห็นรหัสและคิดว่ามันเป็นภาษาที่แตกต่างกันก็อาจจะไม่

a,b,LHS,RHS;
main(){
    a=2; b=2;
    LHS=a; RHS=b;

    //multiply both sides by a
    LHS,RHS *= a; 
    //subtract b squared from both sides
    LHS,RHS -= b*b; 
    //assert that it factors correctly
    if (LHS,RHS != (a+b)*(a-b), b*(a-b)) printf("ERROR!\n");
    //'hard' division, just to be sure the compiler doesn't remove it
    LHS,RHS /=! (a-b);
    //assert that a+a really is b+b
    if (a+a != b+b) printf("ERROR!\n");
    //now just divide them by b
    printf("%d = %d ? ", LHS/b, RHS/b);
    if (RHS = LHS) 
        printf("true!");
    else
        printf("false!");
}

แน่นอนว่ามันไม่ได้ผลเช่นกันเมื่อเขียนด้วยสำนวนที่มากขึ้น#include <stdio.h>และ int ก็ถูกโยนไปข้างหน้าคำประกาศ


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

ก่อนอื่นโปรดทราบว่าใน c ถ้าคุณ 'ลืม' int ในการประกาศมันจะถือว่า int ประเภทเพื่อที่จะย้อนกลับเข้ากันได้กับ k & r c ถัดไปค้นหาผู้ประกอบการในคและใส่ใจกับความสำคัญของมัน ถัดไปให้สังเกต = แทน == ในคำสั่ง if สุดท้าย
LambdaBeta
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.