"Disprove" o último teorema de Fermat [fechado]


49

Escreva um programa, no idioma de sua escolha, que pareça encontrar com êxito um contra-exemplo do Último Teorema de Fermat . Ou seja, encontre os números inteiros a , b , c > 0 e n > 2 de modo que a n + b n = c n .

Claro, você realmente não pode fazê-lo, a menos que haja uma falha na prova de Andrew Wiles. Quero dizer, fingir , contando com

  • estouro inteiro
  • erro de arredondamento de ponto flutuante
  • comportamento indefinido
  • tipos de dados com definições incomuns de adição, exponenciação ou igualdade
  • erros de compilador / intérprete
  • Ou algo nesse sentido.

Você pode codificar algumas ou todas as variáveis a, b, c, ou n, ou procurá-los, fazendo voltas como for a = 1 to MAX.

Este não é um código de golfe; é um concurso para encontrar soluções inteligentes e sutis.


na verdade, você pode ter alguns como todos eles, além do expoente, que deve ser 3 ou superior. Então, 1 ^ 3 + 1 ^ 3 = 1 ^ 3 é assim tão simples.

2
@Iver: 1³ + 1³ = 2; 1³ = 1; 2 # 1
— dan04 23/10

Respostas:


57

J

Na verdade, Fermat cometeu um grande erro: na verdade, é errado para qualquer b, c ou n se a for 1:

   1^3 + 4^3 = 5^3
1
   1^4 + 5^4 = 11^4
1
   1^9 + 3^9 = 42^9
1

Talvez apenas talvez, as regras de precedência de Fermat não fossem estritamente da direita para a esquerda.


19
+1 Estritamente da direita para a esquerda. Apenas para pessoas que leem da esquerda para a direita; a notação normal para a última seria #1^(9 + (3^(9 = (42^9))))
— 2014

11
Sneaky, meu cérebro estava prestes a derreter até que eu vi @ comentário de TheRare
— german_guy

3
Esse é um recurso pretendido de J? Esse é o tipo de coisa que realmente deixaria as pessoas loucas.
— QWR

2
@qwr Em J, toda avaliação é da direita para a esquerda, com algumas exceções. Parece estranho, mas na verdade é bem legal.
— seequ

11
@ dan04 Não é verdade. 1^i.5avalia como 1 1 1 1 1.
— ɐɔıʇǝɥʇuʎs

36

TI-Basic

1782^12+1841^12=1922^12

Saída (verdadeira)

1


11
Eu vi esse episódio tantas vezes, nunca percebi isso. Boa pegada!
— usar o seguinte

11
Esta resposta funciona apenas conforme escrito com o TI-89 sabor TI-Basic. Numa TI-84 + SE, o código apresenta um erro de sintaxe, porque essa versão do TI-Basic não permite espaços. Mas a resposta ainda funciona em uma calculadora mais antiga se você remover espaços, escrevendo 1782^12+1841^12=1922^12.
— Rory O'Kane

11
+1 para usando TI-Basic, foi a minha primeira linguagem de programação :)
— Kik

2
@ThaneBrimhall Essa é a ironia, uma calculadora não um problema de matemática simples
— QWR

35

Java

Esse cara Fermat deve estar dormindo. Eu recebo centenas de soluções para as equações. Apenas converti minha fórmula do Excel para um programa Java.

public class FermatNoMore {
    public static void main(String[] args) {
        for (int n = 3; n < 6; n++)
            for (int a = 1; a < 1000; a++)
                for (int b = 1; b < 1000; b++)
                    for (int c = 1; c < 1000; c++)
                        if ((a ^ n + b ^ n) == (c ^ n))
                            System.out.println(String.format("%d^%d + %d^%d = %d^%d", a, n, b, n, c, n));
    }
}

O ^operador realmente significa XOR em Java, em oposição à exponenciação em texto simples comum


Alguma chance de uma elaboração sobre por que isso funciona?
— Vality 28/06

20
@ Qualidade: ^em Java é xor, não poder.
— marinus

3
esta técnica funciona em quase todas as linguagens baseadas em C
— phuclv

19

C ++

#include <cstdlib>
#include <iostream>

unsigned long pow(int a, int p) {
  unsigned long ret = a;

  for (int i = 1; i < p; ++i)
    ret *= a;

  return ret;
}

bool fermat(int n) {
  // surely we can find a counterexample with 0 < a,b,c < 256;
  unsigned char a = 1, b = 1, c = 1;

  // don't give up until we've found a counterexample
  while (true) {
    if (pow(a, n) + pow(b, n) == pow(c, n)) {
      // found one!
      return true;
    }

    // make sure we iterate through all positive combinations of a,b,c
    if (!++a) {
      a = 1;
      if (!++b) {
        b = 1;
        if (!++c)
          c = 1;
      }
    }
  }

  return false;
}

int main(int argc, char** argv) {
  if (fermat(std::atoi(argv[1])))
   std::cout << "Found a counterexample to Fermat's Last Theorem" << std::endl;
}

Compilado com clang++ -O3 -o fermat fermat.cpp, testado com Ubuntu clang version 3.4.1-1~exp1 (branches/release_34) (based on LLVM 3.4.1):

./fermat 3
Found a counterexample to Fermat's Last Theorem

Obviamente, encontramos a, b, c> 0, de modo que a 3 + b 3 = c 3 (isso também funciona para n = 4, 5, 6, ...).

Imprimir a, bec pode ser um pouco difícil ...


11
@ dan04: Opa, esqueci o ++dentro clang++.
— Ventero 28/06

2
A propósito, isso não é um bug do compilador. O padrão C (e C ++) permite fazer qualquer coisa aqui, como val.upode estourar (seria diferente se fosse uint32_t). Além disso, esse código também usa de unionmaneira incorreta (de acordo com o padrão, você não pode gravar em um campo e ler o outro campo), mas isso é permitido por muitos compiladores (de acordo com a documentação).
— precisa

3
A razão disso é permitida é uma seção do padrão C ++ que diz: Um loop que, fora da instrução for-init no caso de uma instrução for, * não faz chamadas para funções de E / S da biblioteca e * não acessar ou modificar objetos voláteis e * não executar operações de sincronização (1.10) ou operações atômicas (Cláusula 29) podem ser assumidas pela implementação para terminar.
— dan04

3
@ dan04 Essa redação exata foi realmente removida do padrão em um rascunho posterior, consulte US 38 em open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3196.htm - mas é claro que só foi generalizada. Esta é a razão pela qual a impressão a,b,c(ou qualquer outra coisa) fermat()faz com que a função nunca retorne.
— Ventero

8
Argh, eu estava indo para postar esse. Para quem está confuso: John Regehr tem uma boa explicação aqui .
— Voo 28/06

13

Java

Parece que o teorema vale para n = 3, mas eu encontrei contra-exemplos para n = 4:

public class Fermat {
    public static int p4(final int x) {
        return x * x * x * x;
    }

    public static void main(final String... args) {
        System.out.println(p4(64) + p4(496) == p4(528));
    }
}

Resultado:

true

Explicação:

Mesmo que os números pareçam pequenos, eles transbordam quando aumentados para a quarta potência. Na realidade, 64 4 + 496 4 = 528 4 - 2 34 , mas 2 34 se torna 0 quando restrito a int (32 bits).


Você pode explicar isso?
— Anubian Noob

@AnubianNoob done
— aditsu

9

Pitão

import math
print math.pow(18014398509481984,3) + math.pow(1, 3) \
      == math.pow(18014398509481983,3)

Quem diz que c deve ser maior que um e b ?


2
Ele é impresso Trueporque math.pow retorna números de ponto flutuante e eles não têm precisão suficiente para obter a resposta correta False.
— kernigh

5

GolfScript

# Save the number read from STDIN in variable N and format for output.

:N"n="\+

{
  [{100rand)}3*] # Push an array of three randomly selected integers from 1 to 100.
  .{N?}/         # Compute x**N for each of the three x.
  +=!            # Check if the sum of the topmost two results equals the third.
}{;}while        # If it doesn't, discard the array and try again.

# Moar output formatting.

~]["a=""\nb=""\nc="""]]zip

Essa abordagem encontra várias soluções diferentes. Por exemplo:

$ golfscript fermat.gs <<< 3
n=3
a=43
b=51
c=82

Como funciona

A primeira linha deve começar com a ~para interpretar a entrada. Em vez de, por exemplo, o número 3, a variável Ncontém a sequência 3\n.
Enquanto 2 3 ?calcula 3 , 2 N ?pressiona o índice de um caractere com o código ASCII 2 em N(-1 para não encontrado).
Desta forma, 43 N ?e 82 N ?empurrar -1e 51 N ?empurrões 0(51 é o código de caracteres ASCII de 3).
Desde então -1 + 0 = -1, a condição é satisfeita e (43,51,82)é uma "solução".


4

C

Bem, é claro que vocês estão encontrando contra-exemplos, continuam obtendo estouros de número inteiro. Além disso, você está sendo muito lento ao iterar em c também. Esta é uma maneira muito melhor de fazer isso!

#include <stdio.h>
#include <math.h>

int main(void) {
  double a, b, c;
  for (a = 2; a < 1e100; a *= 2) {
    for (b = 2; b < 1e100; b *= 2) {
      c = pow(pow(a, 3) + pow(b, 3), 1.0/3);
      if (c == floor(c)) {
        printf("%f^3 + %f^3 == %f^3\n", a, b, c);
      }
    }
  }
  return 0;
}

double pode ser ótimo no intervalo, mas ainda falta um pouco de precisão ...


4

C

Todos odiamos estouros de número inteiro; portanto, usaremos um pequeno expoente ne algumas conversões de ponto flutuante. Mas ainda assim o teorema não se sustentaria a = b = c = 2139095040.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>

int a, b, c;
int n;

int disprove(int a, int b, int c, int n)
{
    // Integers are so prone to overflow, so we'll reinforce them with this innocent typecast.
    float safe_a = *((float *)&a);
    float safe_b = *((float *)&b);
    float safe_c = *((float *)&c);

    return pow(safe_a, n) + pow(safe_b, n) == pow(safe_c, n);
}

int main(void)
{
    srand(time(NULL));

    a = b = c = 2139095040;
    n = rand() % 100 + 3;

    printf("Disproved for %d, %d, %d, %d: %s\n", a, b, c, n, disprove(a, b, c, n) ? "yes" : "no");
}

Resultado:

Disproved for 2139095040, 2139095040, 2139095040, 42: yes

Disproved for 2139095040, 2139095040, 2139095040, 90: yes

No IEEE 754, o número 2139095040, ou 0x7F800000, representa o infinito positivo nos tipos de ponto flutuante de precisão única. Todas as pow(...)chamadas retornariam + Infinito e + Infinito iguais a + Infinito. Uma tarefa mais fácil seria refutar o teorema de Pitágoras usando 0x7F800001 (Quiet NaN) que não é igual a si mesmo de acordo com o padrão.


2

Javascript

var a, b, c, MAX_ITER = 16;
var n = 42;
var total = 0, error = 0;

for(a = 1 ; a <= MAX_ITER ; a++) {
  for(b = 1 ; b <= MAX_ITER ; b++) {
    for(c = 1 ; c <= MAX_ITER ; c++) {
      total++;
      if(Math.pow(a, n) + Math.pow(b, n) == Math.pow(c, n)) {
        error++;
        console.log(a, b, c);
      }
    }
  }
}

console.log("After " + total + " calculations,");
console.log("I got " + error + " errors but Fermat ain't one.");

42 é mágico, você sabe.

> node 32696.js
After 2176 calculations,
I got 96 errors but Fermat ain't one.

E também Wiles não é um.

Javascript Numbernão é grande o suficiente.


2

T-SQL

Para refutar o teorema de Fermat, precisamos apenas encontrar um contra-exemplo. Parece que ele era super preguiçoso, e só tentou isso por permutação muito pequena. Na verdade, ele nem estava tentando. Encontrei um exemplo de contador em apenas 0 <a, b, c <15 e 2 <e <15. Desculpe, mas eu sou um jogador de golfe, então desgolfo esse código mais tarde!

with T(e)as(select 1e union all select (e+1) from T where e<14)select isnull(max(1),0)FROM T a,T b,T c,T e where e.e>2 and power(a.e,e.e)+power(b.e,e.e)=power(c.e,e.e)

Retorna 1, o que significa que encontramos um exemplo contrário!

O truque é que, embora o primeiro e pareça um alias, na verdade é uma maneira sorrateira de alterar o tipo de dados de e de um tipo de ponto int para um ponto flutuante equivalente a um dobro. Quando chegamos aos 14, estamos além da precisão de um número de ponto flutuante, para que possamos adicionar 1 a ele e ainda não perdemos nada. A minificação é uma boa desculpa para explicar minha aparentemente dupla declaração boba de um alias de coluna no rcte. Se eu não fizesse isso, ela transbordaria muito antes de chegarmos a 14 ^ 14.


1

Javascript

Parece que esse cara estava bem em algo. Sobre drogas, se você me perguntar. Dadas as restrições, nenhum conjunto de valores pode ser encontrado para o qual o teorema é verdadeiro.

var a = 1,
    b = 1,
    c = 1,
    n = 3,
    lhs = (a^n + b^n),
    rhs = c^n;

alert(lhs === rhs);

Como em Java, o ^operador é o operador XOR bit a bit em JavaScript. A maneira correta de calcular a potência de um número é usar Math.pow.


2
Para Fermat, o expoente ( n) deve ser >= 3.
— recursivo

Bom ponto, o código ainda funciona embora :)
— thomaux

0

Outro contra-exemplo BÁSICO

10 a = 858339
20 b = 2162359
30 c = 2162380
40 IF (a^10 + b^10) = c^10 THEN
50   PRINT "Fermat disproved!"
60 ENDIF
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.