Классическая ошибка доказательства [закрыто]


18

Фон

Итак, мы все знаем классическое доказательство, которое выглядит так:

а = Ь
a² = AB
a² - b² = AB - b²
(аb) (а + б) = Ь (аb)
(а + б) = Ь
Ь + B = B
2b = Ь
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).

Помните, это конкурс популярности, поэтому побеждает наибольшее количество голосов.
Кроме того, в новой версии математики под названием «Математика 2.0» используются стандартные лазейки, которые автоматически лишают законной силы доказательство.


Вот ссылка на Википедию о математической ошибке, чтобы люди могли лучше понять

3
Я голосую за то, чтобы закрыть этот вопрос как не по теме, потому что скрытые проблемы больше не обсуждаются на этом сайте. meta.codegolf.stackexchange.com/a/8326/20469
кошка,

Ответы:


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

ideone

Подсказка:

,

Объяснение:

Две строки, заканчивающиеся запятыми, заставляют программу вести себя не так, как она. Без запятых метод принимает один аргумент a, устанавливает его bравным a, выполняет преобразования из каждого доказательства (кроме некоторых отсутствующих скобок, он не делится на 0) и выводит результат (с вводом 3 , это вывело бы «-1 = -1». Однако с запятой в конце b = aстрока становится частью сигнатуры метода, что означает, что она объявляет второй аргумент со значением по умолчанию. Вызов метода в конце передается в результат STDOUT.write($/), равный 1 (число байтов, записанных в STDOUT, поскольку $/он предопределен для символа новой строки.) Таким образом, a равен 3, а b равен 1, в результате чего уравнение начинается с «3 = 1». мусор.


Хороший трюк с твоими переводами строки.
LegionMammal978

Не могли бы вы добавить объяснение нерубистам?
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;
};

Попробуй это здесь !

Так что же происходит?

Первое, что вы могли заметить, это «запрещенные триграфы». Но помните, это GolfScript, а не C! Также, вероятно, заметил, что он на самом деле не говорит «int main ()», он говорит «1nt main ()». В GolfScript «1» означает толчок 1 в стек, а «nt main» обрабатывается как две неинициализированные переменные, которые ничего не делают. Две круглые скобки сначала добавляют 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.

Вывод, когда areEqual(4,4)вызывается (или любая другая пара чисел на самом деле):

false

Почему?

В Прологе оператор "=" не является аффектом; это «Объединение». Поэтому Amod = Amod * Aтерпит неудачу, потому Amodчто уже был объединен с A, и, следовательно, не может быть объединен с Amod * A. Пролог сразу же прекращает выполнение текущего правила и возвращается false.


2
Я думаю, что все должно быть наоборот, вы должны вывести «true», когда два значения различны, а не «false», когда они равны ^^ '
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: он не совсем соответствует правилам, он выводит только, если переменные равны или нет.

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. Спасибо Алексу Ван Лью за то, что он указал, что это относится не только к Javascript.


NaNне NaNсоответствует спецификациям IEEE float. На самом деле, быстрый способ проверить, есть ли у вас NaNC, - это сравнить его с самим собой. Так что это относится ко всем языкам, а не только к JS.
Алекс Ван Лью

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, поэтому конец любого ответа здесь не должен быть «верным»
Каин

Я думал о БОНУСЕ закулисным. Ничего. «Вместо того, чтобы печатать знак равенства, вы можете распечатать только две переменные (aMod и bMod), а затем иметь код, который, по-видимому, сравнивает две переменные на равенство, но на самом деле заключается в том, что они равны (и печатает некоторую форму true) «.
mbomb007

0

С

Классическая ошибка доказательства требует классического синтаксического недопонимания. К сожалению, я встречал некоторых разработчиков «только высокого уровня», которые убеждены, что 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. Затем найдите оператор, в c и обратите внимание на его приоритет. Далее обратите внимание на = вместо == в последнем операторе if.
ЛямбдаБета
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.