고전적인 증거 오류


18

배경

따라서 우리 모두는 다음과 같은 고전적인 증거를 알고 있습니다.

A = B
a² = AB
a² - b² = AB - b²
(AB) (a + 나) = B (AB)
(a + 나) = 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로 나눈 다음 b (또는 a)로 나눠야합니다. 그런 다음 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).

이것은 인기 콘테스트이므로 기억해야 할 투표 수가 가장 많습니다.
또한 Mathematics 2.0이라는 새로운 버전의 수학에서는 표준 허점을 사용하여 자동으로 증명을 무효화합니다.


다음 은 사람들이 더 잘 이해할 수 있도록 수학 오류의 위키 백과 링크입니다.

3
나는이 문제를 주제로 다루지 않기로 결심했다. 왜냐하면이 사이트에서 미숙 한 도전은 더 이상 주제가 아니기 때문이다. meta.codegolf.stackexchange.com/a/8326/20469
고양이

답변:


17

자바 스크립트

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

파이썬 2

모두가 파이썬을 알고 있기 때문에 분명하지만, 여기 내 시도가 있습니다.

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($/)

이데온

힌트:

,

설명:

쉼표로 끝나는 두 줄은 프로그램과 다르게 동작합니다. 쉼표가 없으면이 메서드는 단일 인수를 가져와 동일하게 a설정 하고 각 괄호에서 교정을 통해 변환을 수행하고 (괄호가 누락 된 경우를 제외하고 0으로 나누지 않음) 결과를 출력합니다 (3의 입력) 쉼표를 사용하면 행이 메소드 서명의 일부가되어 기본값으로 두 번째 인수를 선언 함을 의미합니다. 마지막에 메소드 호출은 결과 는 1 ( 개행 문자로 사전 정의 되므로 STDOUT에 쓴 바이트 수)입니다 . 따라서 a는 3이고 b는 1이므로 방정식은 "3 = 1"로 시작합니다. 쓰레기.bab = aSTDOUT.write($/)$/


줄 바꿈과 함께 좋은 트릭.
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;
};

여기에서 보십시오 !

무슨 일이야?

가장 먼저 눈에 띄는 것은 "금지 된 3 점"입니다. 그러나 이것은 C가 아닌 GolfScript입니다. 또한 실제로는 "int main ()"이 아니라 "1nt main ()"이라고 말합니다. GolfScript에서 "1"은 스택에 1을 넣는 것을 의미하며 "nt main"은 초기화되지 않은 두 개의 변수로 처리되며 아무것도하지 않습니다. 두 괄호는 먼저 스택의 최상위 번호에 1을 더한 다음 하나를 빼서 본질적으로 취소합니다. 괄호는 스택으로 밀려 들어가는 블록을 나타내며 세미콜론은 바로 튀어 나옵니다. 결국, 우리는 원래의 "1"을 눌렀으며 GolfScript 프로그램이 끝나면 스택이 인쇄됩니다. 이 답변은 영감을받은 하나.


3 단점이 감지되었습니다. 자동 -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.

areEqual(4,4)호출 될 때의 출력 (또는 실제로 다른 두 숫자) :

false

왜?

프롤로그에서 연산자 "="는 영향을받지 않습니다. "통일"입니다. 따라서 와 (과) 이미 통합되었으므로 Amod = Amod * A실패 할 수 있습니다 . 그런 다음 Prolog는 즉시 현재 규칙 실행을 중지하고을 반환합니다 .AmodAAmod * Afalse


2
나는 그것이 다른 방법이어야한다고 생각합니다. 두 값이 다를 때 "true"를 출력해야합니다. 두 값이 같을 때 "false"가 아닙니다 ^^ '
Katenkyo

1

자바 스크립트

//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 : 규칙을 정확하게 따르지 않고 변수가 같거나 같지 않은 경우에만 출력합니다.

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은 IEEE float 사양에 의해 NaN과 같지 않습니다. 이는 Javascript에만 적용되지 않는다는 점을 지적한 Alex Van Liew에게 감사합니다.


NaNNaNIEEE float 사양 과 같지 않습니다 . 실제로 NaNC가 있는지 테스트하는 빠른 방법 은 자체 C와 비교하는 것입니다. 따라서 이것은 JS뿐만 아니라 모든 언어에 적용됩니다.
Alex Van Liew

1
@AlexVanLiew 재미있는. 나는 그것을 몰랐다! 좋아, 내 대답을 약간 변경하고 마감일에 크레딧을 추가하십시오.
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

원래 오류의 끝은 2 = 1이므로 여기서 답변의 끝은 "true"가되어서는 안됩니다.
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를 '잊어 버린 경우'는 k & r c와 역 호환 가능하기 위해 int 유형을 가정합니다. 다음으로 c에서 연산자를 찾아 우선 순위에주의하십시오. 마지막 if 문에서 == 대신 =를 참고하십시오.
LambdaBeta
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.