Класичний доказ помилки [закрито]


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

Пам'ятайте, що це змагання за популярність, тому виграє найбільша кількість нагород.
Крім того, нова версія математики під назвою Mathematics 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.


Ого. Це було дуже розумно, «випадково» забувши додати крапки з комою, що робить (майже) всю програму реченням на перебіг.
користувач155698

3

Пітон 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($/)

ідеоне

Підказка:

,

Пояснення:

Два рядки, які закінчуються комами, призводять до того, що програма поводиться інакше, ніж це було б. Без коми цей метод приймає єдиний аргумент 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

Чому?

У Prolog оператор "=" не є афектом; це "Об'єднання". Тому Amod = Amod * Aне вдається через те, Amodщо вже було уніфіковано A, і, таким чином, неможливо бути об'єднаним Amod * A. Потім Prolog негайно припиняє виконання поточного правила і повертається 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 поплавковими характеристиками. Завдяки Alex Van Liew за те, що він зазначив, що це стосується не лише Javascript.


NaNне відповідає NaNспецифікаціям IEEE float. Насправді, швидкий спосіб перевірити, чи є NaNу вас C, - це порівняти його з самим собою. Тож це стосується всіх мов, а не лише JS.
Alex Van Liew

1
@AlexVanLiew Цікаво. Я цього не знав! Гаразд, трохи змінивши свою відповідь і додавши кредит там, де це належить.
Стефнотч

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

Вихід:

-3 = 3

Чому?

[a: b] - це карта, а не список. Я не такий підлий, я знаю :(


Ви повинні мати a рівну b в кінці.
mbomb007

Кінець початкової помилки - 2 = 1, тому кінець будь-якої відповіді тут не повинен бути "правдивим"
Каїн

Я думав, що БОНУС неприхильний. Не зважай. "Замість того, щоб друкувати знак рівності, ви можете роздрукувати лише дві змінні (aMod і bMod), а потім мати код, який видається для порівняння двох змінних для рівності, але в дійсності полягає в тому, що вони рівні (і друкує певну форму істини) . "
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.
LambdaBeta
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.