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