Klasik İspat Yanlışlığı [kapalı]


18

Arkaplan

Yani, hepimiz böyle giden klasik kanıtı biliyoruz:

a = b
a² = ab
a² - b² = ab - b²
(ab) (a + b) = B (ab)
(a + b) = b
b + b = b
2b = b
2 = 1 (ha ha!)
ki Tabii ki, hata 0'a bölünemez. a = b, a - b = 0 olduğundan, 0 ile gizli bir bölünme vardı.

Meydan okuma

Bu kanıtı çoğaltmanız gerekiyor. İlk olarak, iki eşit a ve b tamsayısını (onlara ne dediğiniz önemli değildir) eşit olarak bildirin. Daha sonra aMod ve bMod'un a ve b'nin değiştirilebilir sürümleri olduğunu ve başlangıçta sırasıyla a ve b'ye eşit olduğunu bildirin. Her ikisini de a ile çarpmanız ve ardından b * b'yi her ikisinden de çıkarmanız gerekir. Daha sonra a - b ile bölmelisiniz ve sonra almak için b (veya a) ile bölmelisiniz. Ardından, aMod ve bMod'u, aralarında eşittir işaretiyle yazdırın.

Underhanded

Elbette, a ve b'yi eşit olarak bildirdiğiniz için a - b = 0 ve 0'a bölmek hataya neden olur. Bu yüzden yaratıcı bir şekilde sahte olmalısın. Ayrıca, kanıtı çoğaltmaya çalıştığınız için, aMod ve bMod üzerindeki tüm işlemlerin sonucu yazdırıldığında eşit olmamalıdır. Tam olarak 2 ve 1'e eşit olmak zorunda değiller, sadece eşit olmayan iki sayı.

İşte bir örnek:

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

Belki en iyisi değil, ama konuyu göstermektedir.

Bonus Underhanded

Eşittir işaretini yazdırmak yerine, yalnızca iki değişkeni (aMod ve bMod) yazdırabilir ve ardından iki değişkeni eşitlikle karşılaştırmak için görünen ancak gerçekte eşit olduklarını (ve bir şekilde yazdırdıklarını true) belirten bir koda sahip olabilirsiniz .

Unutmayın, bu bir popülerlik yarışmasıdır, bu yüzden en yüksek sayıda oylar kazanır.
Ayrıca, Mathematics 2.0 adlı yeni bir matematik sürümü, standart boşlukların kullanımını otomatik olarak bir kanıtı geçersiz kılmıştır.


İşte insanların daha iyi anlayabilmesi için matematiksel yanlışlığın Wikipedia bağlantısı

3
Bu soruyu konu dışı olarak kapatmak için oy kullanıyorum çünkü el altında kalan zorluklar artık bu sitede konuyla ilgili değil. meta.codegolf.stackexchange.com/a/8326/20469
kedi

Yanıtlar:


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

Çıktı:

[1, NaN]

0/0 = NaN olduğuna dikkat edin

İpucu

Birkaç noktalı virgül eklemeyi deneyin.
Bu program aslında var a=3,b=3,a2=3,b2=3[a2,b2]=...=[a2/(a-b),b2/(a-b)];console.log([a2/a,b2/a]).
Ve NaN de öyle [3/0,undefined/0]/3.


Vay. Bu çok zekiydi, "yanlışlıkla" noktalı virgül eklemeyi unutuyordu (neredeyse) tüm programı sürekli bir cümle haline getirdi.
user155698

3

Python 2

Herkesin Python'u bildiğinden eminim, ama işte benim girişimim:

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)

Çıktı True.

İpucu:

Bölümümü kontrol et.


çünkü herkes Python kullanıyor .
Python'u

@rpax Demek istediğim buydu.
mbomb007

Üzgünüm, cevabını düzgün okumadım.
rpax

2

Yakut

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

İpucu:

,

Açıklama:

Virgülle biten iki satır, programın olduğundan farklı davranmasına neden olur. Virgül olmadan, yöntem tek bir argüman alır a, beşit olarak ayarlanır a, her birinde ispattan dönüşümleri gerçekleştirir (bazı eksik parantezler hariç, 0'a bölünmez) ve sonucu çıkarır (3 girişiyle) Sondaki virgülle, b = asatır yöntem imzasının bir parçası olur, bu da varsayılan değerle ikinci bir bağımsız değişken bildirdiği anlamına gelir . Sondaki yöntem çağırma sonucu STDOUT.write($/)1 olan (STDOUT'a yazdığı bayt sayısı, $/yeni satır karakteri olarak önceden tanımlandığı için.) Yani a 3 ve b 1'dir, bu da denklemin "3 = 1" olarak başlamasıyla sonuçlanır. çöp dışarı.


Newline'larınızla güzel bir numara.
LegionMammal978

Rubyist olmayanlar için bir açıklama ekleyebilir misiniz?
kirbyfan64sos

@ kirbyfan64sos Elbette, bitti.
histokrat

2

GolfScript

Uyarı: Bu program biraz hile yapıyor, çünkü aMod ve bMod yazdırmıyor

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

Burada deneyin !

Yani, ne oluyor?

Fark etmiş olabileceğiniz ilk şey "yasak trigraflar" dır. Ama unutmayın, bu C değil GolfScript! Ayrıca, muhtemelen "int main ()" demediğini fark etti, "1nt main ()" diyor. GolfScript'te "1", yığına 1 itme anlamına gelir ve "nt main", hiçbir şey yapmayan iki başlatılmamış değişken olarak işlenir. İki parantez önce yığının en üst numarasına 1 ekler ve sonra bir tane çıkarır, temelde kendilerini iptal ederler. Köşeli parantezler yığına itilen bir bloğu belirtir ve ardından noktalı virgül onu hemen fırlatır. Sonunda, sadece itilen orijinal "1" e sahibiz ve bir GolfScript programının sonunda yığın yazdırılır. Bu cevap esinlenerek bu one.


Trigraflar algılandı. Otomatik -1 sisteminin etkinleştirilmesi. Hata: -1 başarısız oldu (4792, RPLS)
CalculatorFeline

Bu sinsi, çünkü sizi kandıramayacağını düşünmek için sizi kandırıyor. +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.

Ne zaman areEqual(4,4)çağrılır (veya gerçekten başka herhangi bir sayı):

false

Neden?

Prolog'da "=" işleci bir ilgi alanı değildir; "Birleşme". Bu nedenle Amod = Amod * Abaşarısız olur, çünkü Amodzaten birleşiktir Ave bu nedenle birleştirilemez Amod * A. Prolog hemen geçerli kuralı yürütmeyi derhal durdurur ve geri döner false.


2
Bence başka bir yol olmalı, iki değer farklı olduğunda "doğru" çıktı, eşit olduğunda "yanlış" değil ^^ '
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);

Çıktı:
http://jsbin.com/furino/2/edit?js,output JsBin bu kodu yürütemiyor gibi görünüyor. Bunun yerine tarayıcı konsolunu kullanın.

Neden?

scrollMaxX ve screenX zaten var olan değişkenlerdir. Tarayıcıda yerleşik olarak bulunurlar. Bu nedenle sonuç değişebilir. Let anahtar kelimesi yalnızca geçici olarak değerlerini değiştirir.

Başka bir JavaScript: Kurallara tam olarak uymaz, yalnızca değişkenler eşitse veya değilse oluşur.

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

Neden?

NaN, IEEE şamandıra spesifikasyonlarına göre NaN'ye eşit değildir. Bunun sadece Javascript için geçerli olmadığını belirttiği için Alex Van Liew'a teşekkürler.


NaNNaNIEEE kayan nokta özelliklerine eşit değildir . Aslında, NaNC'de olup olmadığınızı test etmenin hızlı bir yolu onu C ile karşılaştırmaktır. Bu sadece JS için değil, tüm diller için geçerlidir.
Alex Van Liew

1
@AlexVanLiew İlginç. Bunu bilmiyordum! Tamam, cevabımı biraz değiştiriyorum ve zamanı geldiğinde kredi ekliyoruz.
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})

Çıktı:

-3 = 3

Neden?

[a: b] liste değil haritadır. Çok sinsi değil, biliyorum :(


Sonunda a eşit olması gerekiyor b.
mbomb007

Orijinal yanlışlığın sonu 2 = 1'dir, bu yüzden burada herhangi bir cevabın sonu "doğru" olmamalıdır
Cain

El değmemiş BONUS'u düşünüyordum. Boşver. "Eşittir işaretini yazdırmak yerine, yalnızca iki değişkeni (aMod ve bMod) yazdırabilir ve ardından iki değişkeni eşitlikle karşılaştırmak için görünen, ancak gerçekte eşit olduklarından (ve bir çeşit doğru yazdırdığından) kod yazabilirsiniz. ."
mbomb007

0

C

Klasik kanıt yanılgısı, klasik C sözdizimi yanlış anlaşılmasını gerektirir. Ne yazık ki bu koda benzer sonuçlar nedeniyle C'nin bozuk olduğuna ikna olan bazı "sadece yüksek seviyeli" geliştiricilerle tanıştım. C'nin nasıl çalıştığını biliyorsanız, oldukça açık hale gelir, ancak kodu gördüyseniz ve farklı bir dil olduğunu varsayarsanız, olmayabilir.

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

Tabii #include <stdio.h>deklarasyonların önüne ve int atılmış daha deyimsel olarak yazıldığında pek işe yaramaz .


Yine de nasıl çalışır?
CalculatorFeline

İlk olarak, c'de int'i bir bildirimde 'unutursanız', k & r c ile geriye doğru uyumlu olması için int türünü varsaydığını unutmayın. Sonra, c operatörüne bakın ve önceliğine dikkat edin. Sonra son if deyimindeki == yerine == dikkat edin.
LambdaBeta
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.