古典的証明の誤り[閉じた]


18

背景

したがって、私たちは皆、次のような古典的な証明を知っています:

a =
ba²=
aba²-b²= ab-b²
(ab)(a + b)= b(ab)
(a + b)= b
b + b = b
2b = b
2 = 1(ハハ!)
Ofもちろん、間違いは、0で除算できないことです。a= bであるため、a-b = 0であるため、0による隠れた除算がありました。

チャレンジ

この証明を複製する必要があります。まず、等しい2つの整数aとb(それらを何と呼ぶか​​は関係ありません)を宣言します。次に、aModおよびbModを、aおよびbの変更可能なバージョンで、最初はそれぞれaおよびbに等しいと宣言します。両方にaを掛けてから、両方からb * bを引く必要があります。次に、a-bで除算してから、b(またはa)で除算して取得する必要があります。次に、aModとbModを等号で印刷します。

アンダーハンド

もちろん、aとbを等しいと宣言したため、a-b = 0であり、0で割るとエラーが発生します。だからあなたは創造的にそれを偽造しなければなりません。また、プルーフを複製しようとしているため、aModおよびbModのすべての操作の結果は、印刷時に等しくなってはいけません。正確に2と1である必要はありません。2つの数値は等しくありません。

以下に例を示します。

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

最良のものではないかもしれませんが、ポイントを示しています。

ボーナスアンダーハンド

等号を印刷する代わりに、2つの変数(aModとbMod)だけを印刷して、2つの変数を比較して等しいかどうかを確認するコードを作成できますが、実際にはそれらは等しい(およびの形式を印刷しますtrue)。

これは人気コンテストであるため、最大数の賛成票が勝ちます。
また、数学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])です。
そして、NaNは[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

ヒント:

私の部門を確認してください。


誰もがPythonを使用しているからです。私はpythonを知っていますが、めったに使用しません
-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($/)

イデオン

ヒント:

説明:

コンマで終わる2行は、プログラムの動作を異なるものにします。コンマがない場合、メソッドは単一の引数を取り、等しい値にa設定ba、それぞれの証明から変換を実行します(括弧が欠落しているため、0で除算しません)、結果を出力します(入力が3の場合) 、 "-1 = -1"を出力します。ただし、末尾のコンマを使用すると、b = a行はメソッドシグネチャの一部になり、デフォルト値で2番目の引数を宣言します。最後のメソッド呼び出しは、の結果、STDOUT.write($/)1(STDOUTに書き込んだバイト数$/。改行文字に事前定義されているため)。したがって、aは3で、bは1です。その結果、式は「3 = 1」から始まります。ゴミ出し。


改行を使った素敵なトリック。
LegionMammal978

非ルビイストの説明を追加していただけますか?
kirbyfan64sos

@ kirbyfan64sosはい、できました。
-histocrat

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

ここで試してみてください

どうしたの?

あなたが最初に気づいたかもしれないことは「禁じられた三部作」です。ただし、これはCではなくGolfScriptです!また、実際には「int main()」とは言わず、「1nt main()」と言うことに気付いたでしょう。GolfScriptでは、「1」はスタックに1をプッシュすることを意味し、「nt main」は2つの初期化されていない変数として処理されますが、何も実行されません。2つの括弧は、最初にスタックの一番上の番号に1を加算し、次に1を減算し、本質的にそれらを取り消します。括弧は、スタックにプッシュされるブロックを示し、セミコロンはすぐにそれをポップします。したがって、最後にプッシュされた元の「1」だけがあり、GolfScriptプログラムの最後にスタックが印刷されます。この答えはこれに触発されました


トライグラフが検出されました。自動-1システムをアクティブにします。エラー:-1が失敗しました(4792、RPLS)
CalculatorFeline

これは、あなたをだまして失敗したと思わせるためにだまされているからです。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.

when areEqual(4,4)が呼び出されたとき(または実際に他のいくつかの数字):

false

どうして?

プロローグでは、演算子「=」は影響を受けません。それは「統一」です。したがって、すでにに統合されているためAmod = Amod * A失敗します。その後、Prologは現在のルールの実行を即座に停止し、戻ります。AmodAAmod * Afalse


2
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は既に存在する変数です。これらはブラウザに組み込まれています。したがって、結果は異なる場合があります。letキーワードは、一時的に値を変更するだけです。

別のJavaScriptの1つ:ルールに厳密に従っていません。変数が等しいかどうかだけを出力します。

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

どうして?

IEEE float仕様では、NaNはNaNと等しくありません。これはJavascriptに適用されるだけではないことを指摘してくれたAlex Van Liewに感謝します。


NaNNaNIEEEのfloat仕様では等しくありません。実際、NaNC を持っているかどうかをテストする簡単な方法は、それをCと比較することです。したがって、これはJSだけでなく、すべての言語に適用されます。
アレックスヴァンリュー

1
@AlexVanLiew興味深い。知らなかった!OK、私の答えをわずかに変更し、当然のことながらクレジットを追加します。
-Stefnotch

0

ファントム

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

元の誤acyの終わりは2 = 1であるため、ここでの答えの終わりは「真実」であってはなりません。
カイン

私はボーナスを手に負えないと考えていました。気にしないで。「等号を印刷する代わりに、2つの変数(aModとbMod)だけを印刷して、2つの変数を比較して等しいかどうかを確認できますが、実際にはそれらは等しい(および何らかの形式のtrueを印刷します) 」
mbomb007

0

C

古典的な証明の誤りには、古典的な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をスローし、より慣用的に記述すると、あまりうまく機能しません。


それはどのように機能しますか?
電卓

最初にcで宣言内のintを「忘れる」場合、k&r cとの後方互換性を保つためにint型と見なされることに注意してください。次に、cの演算子を調べて、その優先順位に注意してください。次に、最後のifステートメントの==の代わりに=に注意してください。
ラムダベータ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.