Classic Proof Fallacy [zamknięte]


18

Tło

Wszyscy znamy klasyczny dowód, który wygląda następująco:

A = B
a² = AB
a² - b² = AB - b²
(ab), (A + B) = b (ab),
(A + B) = b
b + b =
2b = B
2 = 1 (Ha!)
O Oczywiście błąd polega na tym, że nie można podzielić przez 0. Ponieważ a = b, a - b = 0, więc podział był ukryty przez 0.

Wyzwanie

Musisz powtórzyć ten dowód. Najpierw zadeklaruj dwie liczby całkowite a i b (nie ma znaczenia, jak je nazwiesz) równe. Następnie zadeklaruj aMod i bMod jako modyfikowalne wersje aib, początkowo równe odpowiednio aib. Musisz je pomnożyć przez a, a następnie odjąć b * b od obu. Musisz podzielić przez -b, a następnie podzielić przezb (lub a), aby uzyskać. Następnie wydrukuj aMod i bMod ze znakiem równości między nimi.

Podstępni

Oczywiście, ponieważ zadeklarowałeś aib równe, a - b = 0, a dzielenie przez 0 powoduje błąd. Musisz więc kreatywnie to sfałszować. Ponadto, ponieważ próbujesz odtworzyć dowód, wynik wszystkich operacji na aMod i bMod nie może być równy po wydrukowaniu. Nie muszą równać się dokładnie 2 i 1, tylko dwie liczby, które nie są równe.

Oto przykład:

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

Może nie najlepszy, ale ilustruje sens.

Bonus Underhanded

Zamiast drukować znak równości, możesz wydrukować tylko dwie zmienne (aMod i bMod), a następnie mieć kod, który wydaje się porównywać dwie zmienne pod kątem równości, ale w rzeczywistości leży, że są one równe (i drukuje jakąś formę true).

Pamiętaj, że jest to konkurs popularności, więc wygrywa najwyższa liczba głosów pozytywnych.
Ponadto nowa wersja matematyki o nazwie Mathematics 2.0 wykorzystała standardowe luki automatyczne unieważniające dowód.


Oto link Wikipedii do

3
Głosuję za zamknięciem tego pytania jako nie na temat, ponieważ słabe wyzwania nie są już na ten temat na tej stronie. meta.codegolf.stackexchange.com/a/8326/20469
kot

Odpowiedzi:


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

Wynik:

[1, NaN]

Zauważ, że 0/0 = NaN

Wskazówka

Spróbuj dodać kilka średników.
Ten program jest w rzeczywistości var a=3,b=3,a2=3,b2=3[a2,b2]=...=[a2/(a-b),b2/(a-b)];console.log([a2/a,b2/a]).
A NaN jest [3/0,undefined/0]/3.


Łał. Było to bardzo sprytne, „przypadkowo” zapominając o dodaniu średników, dzięki czemu (prawie) cały program jest zdania uruchamiającego.
user155698

3

Python 2

Jestem prawie pewien, że to oczywiste, ponieważ wszyscy znają Python, ale oto moja próba:

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)

Wyprowadza True.

Wskazówka:

Sprawdź mój dział.


ponieważ wszyscy używają Pythona . Znam pytona, ale rzadko go używam
rpax

@rpax Właśnie to miałem na myśli.
mbomb007

Przepraszam, nie przeczytałem poprawnie twojej odpowiedzi.
rpax

2

Rubin

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

Wskazówka:

,

Wyjaśnienie:

Dwa wiersze, które kończą się przecinkami, powodują, że program zachowuje się inaczej niż powinien. Bez przecinków metoda pobiera pojedynczy argument a, ustawia wartość brówną a, wykonuje transformacje z dowodu na każdym (z wyjątkiem niektórych brakujących nawiasów, nie dzieli się przez 0), i zwraca wynik (z wejściem 3 , wyświetli "-1 = -1". Jednak z przecinkiem końcowym b = alinia staje się częścią podpisu metody, co oznacza, że ​​deklaruje drugi argument z wartością domyślną. Wywołanie metody na końcu przechodzi w wynik STDOUT.write($/), który wynosi 1 (liczba bajtów, które zapisał do STDOUT, ponieważ $/jest predefiniowany do znaku nowego wiersza). Zatem a to 3, a b to 1, co powoduje, że równanie zaczyna się od „3 = 1”. wyrzucać śmieci.


Niezła sztuczka z twoimi nowymi liniami.
LegionMammal978

Czy możesz dodać wyjaśnienie nie-rubyistów?
kirbyfan64sos

@ kirbyfan64sos Pewnie, gotowe.
histocrat

2

GolfScript

Ostrzeżenie: ten program trochę oszukuje, ponieważ nie drukuje aMod i 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;
};

Wypróbuj tutaj !

Więc co się dzieje?

Pierwszą rzeczą, którą mogłeś zauważyć, są „zakazane trigrafie”. Pamiętaj jednak, że to jest GolfScript, a nie C! Prawdopodobnie zauważył również, że tak naprawdę nie mówi „int main ()”, ale „1nt main ()”. W GolfScript „1” oznacza pchnięcie 1 na stos, a „nt main” zostaje przetworzone jako dwie niezainicjowane zmienne, które nic nie robią. Dwa nawiasy najpierw dodają 1 do najwyższego numeru stosu, a następnie odejmują jeden, zasadniczo anulując się. Nawiasy kwadratowe oznaczają blok, który zostaje wypchnięty na stos, a następnie średnik od razu go wysuwa. Na koniec mamy po prostu oryginalną cyfrę „1”, która została wypchnięta, a na końcu programu GolfScript stos jest drukowany. Ta odpowiedź została zainspirowana .


Wykryto kaligrafie. Aktywacja systemu automatycznego -1. Błąd: -1 nie powiodło się (4792, RPLS)
CalculatorFeline

Jest to podstępne, ponieważ wabi cię do myślenia, że ​​cię nie oszukał. +1
Rɪᴋᴇʀ

1

Prolog

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.

Dane wyjściowe po areEqual(4,4)wywołaniu (lub jakiejkolwiek innej parze liczb):

false

Dlaczego?

W Prologu operator „=” nie ma wpływu; to „Unifikacja”. Dlatego Amod = Amod * Azawodzi, ponieważ Amodzostał już zjednoczony A, a zatem nie może być zjednoczony Amod * A. Prolog natychmiast przestaje wykonywać bieżącą regułę i wraca false.


2
Myślę, że powinno być na odwrót, musisz podać „prawda”, gdy dwie wartości są różne, a nie „fałsz”, gdy są równe ^^ '
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);

Dane wyjściowe:
http://jsbin.com/furino/2/edit?js,out JsBin nie wydaje się być w stanie wykonać tego kodu. Zamiast tego użyj konsoli przeglądarki.

Dlaczego?

scrollMaxX i screenX to już istniejące zmienne. Są one wbudowane w przeglądarce. Zatem wynik może się różnić. Słowo kluczowe let tylko tymczasowo zmienia swoją wartość.

Kolejny kod JavaScript: nie jest dokładnie zgodny z regułami, wyświetla tylko wtedy, gdy zmienne są równe, czy nie.

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

Dlaczego?

NaN nie jest równy NaN według specyfikacji pływaka IEEE. Podziękowania dla Alexa Van Liewa za zwrócenie uwagi, że nie dotyczy to tylko Javascript.


NaNnie jest równa NaNspecyfikacji pływaka IEEE. W rzeczywistości szybkim sposobem sprawdzenia, czy masz NaNw C, jest porównanie go z samym sobą. Dotyczy to wszystkich języków, nie tylko JS.
Alex Van Liew

1
@AlexVanLiew Ciekawe. Nie wiedziałem tego! Ok, zmieniając nieco moją odpowiedź i dodając kredyt tam, gdzie jest to należne.
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})

Wynik:

-3 = 3

Dlaczego?

[a: b] to mapa, a nie lista. Nie taki podstępny, wiem :(


Powinieneś mieć a równe b na końcu.
mbomb007

Koniec pierwotnego błędu to 2 = 1, więc koniec żadnej odpowiedzi tutaj nie powinien być „prawdziwy”
Kain

Myślałem o BONUSie podstępnym. Nieważne. „Zamiast drukować znak równości, możesz wydrukować tylko dwie zmienne (aMod i bMod), a następnie mieć kod, który wydaje się porównywać dwie zmienne pod kątem równości, ale w rzeczywistości leży to, że są one równe (i drukuje jakąś formę prawdy) . ”
mbomb007

0

do

Błąd klasyczny dowodu wymaga nieporozumienia w klasycznej składni C. Niestety spotkałem programistów „tylko na wysokim poziomie”, którzy są przekonani, że C jest uszkodzony z powodu wyników podobnych do tego kodu. Jeśli wiesz, jak działa C, staje się to dość oczywiste, ale jeśli widziałeś kod i zakładałeś, że jest to inny język, może nie być.

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

Oczywiście nie działa to tak dobrze, gdy jest napisane bardziej idiomatycznie #include <stdio.h>i int jest rzucane przed deklaracjami.


Jak to działa?
CalculatorFeline

Najpierw zauważ, że w c, jeśli „zapomnisz” int w deklaracji, zakłada on int, aby być kompatybilnym wstecz z k & rc. Następnie wyszukaj operator c i zwróć uwagę na jego pierwszeństwo. Następnie zanotuj = zamiast == w ostatniej instrukcji if.
LambdaBeta
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.