"Disprovare" L'ultimo teorema di Fermat [chiuso]


49

Scrivi un programma, nella lingua che preferisci, che sembra trovare con successo un controesempio all'ultimo teorema di Fermat . Cioè, trova numeri interi a , b , c > 0 e n > 2 tali che a n + b n = c n .

Certo, non puoi davvero farlo, a meno che non ci sia un difetto nella prova di Andrew Wiles. Intendo fingere , facendo affidamento

  • overflow intero
  • errore di arrotondamento in virgola mobile
  • comportamento indefinito
  • tipi di dati con definizioni insolite di addizione, esponenziazione o uguaglianza
  • bug del compilatore / interprete
  • o qualcosa del genere.

Si può codificare alcune o tutte le variabili a, b, c, o n, o cercare per loro da fare loop come for a = 1 to MAX.

Questo non è un codice golf; è un concorso per trovare soluzioni intelligenti e sottili.


in realtà, puoi averne uno come tutti oltre all'esponente, che deve essere 3 o superiore. Quindi, 1 ^ 3 + 1 ^ 3 = 1 ^ 3 è così semplice.

2
@Siver: 1³ + 1³ = 2; 1³ = 1; 2 ≠ 1
dan04,

Risposte:


57

J

In realtà, Fermat ha fatto un grosso errore: in realtà è sbagliato per qualsiasi b, c o n se a è 1:

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

Forse solo forse, le regole di precedenza di Fermat non erano strettamente da destra a sinistra.


19
+1 Rigorosamente da destra a sinistra. Solo per le persone che leggono da sinistra a destra; la notazione normale per l'ultima sarebbe1^(9 + (3^(9 = (42^9))))
vedi il

1
Subdolo, il mio cervello stava per sciogliersi fino a quando non ho visto il commento di @ TheRare
german_guy,

3
È questa una caratteristica prevista di J? Questo è il genere di cose che farebbe davvero impazzire le persone.
qwr

2
@qwr In J, tutta la valutazione va da destra a sinistra, con alcune eccezioni. Sembra strano ma in realtà è abbastanza pulito.
Seequ,

1
@ dan04 Non proprio vero. 1^i.5valuta 1 1 1 1 1.
ɐɔıʇǝɥʇuʎs,

36

TI-Basic

1782^12+1841^12=1922^12

Output (vero)

1


1
Ho visto quell'episodio così spesso, non l'ho mai notato. Bella presa!
dom0

1
Questa risposta funziona solo come scritto con TI-89-TI-Basic. Su una TI-84 + SE, il codice presenta un errore di sintassi, poiché quella versione di TI-Basic non consente spazi. Ma la risposta funziona ancora su un vecchio calcolatore se si rimuovono gli spazi, scrivendo 1782^12+1841^12=1922^12.
Rory O'Kane,

1
+1 per l'utilizzo di TI-Basic, è stato il mio primo linguaggio di programmazione :)
Kik

2
@ThaneBrimhall Questa è l'ironia, una calcolatrice che fallisce un semplice problema di matematica
qwr

35

Giava

Questo ragazzo Fermat deve aver dormito. Ricevo centinaia di soluzioni alle equazioni. Ho semplicemente convertito la mia formula Excel in un programma 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));
    }
}

L' ^operatore in realtà significa XOR in Java, al contrario di esponenziale in tipico testo normale


Qualche possibilità su un'elaborazione sul perché funziona?
Vality,

20
@Valità: ^in Java è xor, non potenza.
Marin

3
questo funziona tecnicamente su quasi tutti i linguaggi basati su 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;
}

Compilato con clang++ -O3 -o fermat fermat.cpp, testato con 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

Abbiamo ovviamente trovato a, b, c> 0 in modo che a 3 + b 3 = c 3 (questo funziona anche per n = 4, 5, 6, ...).

Stampare a, bec potrebbe rivelarsi un po 'difficile anche se ...


1
@ dan04: Oops, dimenticato l' ++in clang++.
Ventero,

2
A proposito, questo non è un bug del compilatore. Lo standard C (e C ++) consente di fare qualsiasi cosa qui, così come val.upuò traboccare (sarebbe invece diverso se fosse uint32_tinvece). Inoltre, questo codice utilizza anche unionin modo errato (secondo lo standard, non è possibile scrivere in un campo e leggere l'altro campo), ma questo è consentito da molti compilatori (secondo la loro documentazione).
Konrad Borowski,

3
Il motivo per cui è consentito è una sezione dello standard C ++ che dice: Un ciclo che, al di fuori dell'istruzione for-init nel caso di un'istruzione for, * non effettua chiamate alle funzioni I / O della libreria e * non accedere o modificare oggetti volatili e * non esegue operazioni di sincronizzazione (1.10) o operazioni atomiche (clausola 29) che l'implementazione può concludere.
dan04,

3
@ dan04 Quella formulazione esatta è stata effettivamente rimossa dallo standard in una bozza successiva, vedi US 38 in open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3196.htm - ma ovviamente è stato solo generalizzata. Questo è il motivo per cui la stampa a,b,c(o qualcosa del genere) non fermat()fa mai tornare la funzione.
Ventero,

8
Argh, l'avrei pubblicato così. Per chiunque sia confuso: John Regehr ha una bella spiegazione qui .
Voo,

13

Giava

Sembra che il teorema valga per n = 3, ma ho trovato controesempi per 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));
    }
}

Produzione:

true

Spiegazione:

Anche se i numeri sembrano piccoli, traboccano quando aumentano alla 4a potenza. In realtà, 64 4 + 496 4 = 528 4 - 2 34 , ma 2 34 diventa 0 se limitato a int (32 bit).


Puoi spiegarlo?
Anubian Noob,

@AnubianNoob done
aditsu,

9

Pitone

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

Chi dice che c deve essere maggiore di un e B ?


2
Esso stampa Trueperché i numeri rendimenti Math.pow in virgola mobile, e questi non hanno abbastanza precisione per ottenere la risposta corretta, 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

Questo approccio trova diverse soluzioni. Per esempio:

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

Come funziona

La prima riga dovrebbe iniziare con a ~per interpretare l'input. Invece di, ad esempio, il numero 3, la variabile Ncontiene la stringa 3\n.
Mentre 2 3 ?calcola 3 , 2 N ?inserisce l'indice di un carattere con il codice ASCII 2 in N(-1 per non trovato).
In questo modo, 43 N ?e 82 N ?spingere -1e 51 N ?spinte 0(51 è il codice di carattere ASCII 3).
Da allora -1 + 0 = -1, la condizione è soddisfatta ed (43,51,82)è una "soluzione".


4

C

Beh, naturalmente voi tutti state trovando controesempi, continuate a ricevere overflow di numeri interi. Inoltre, stai anche rallentando iterando anche su c. Questo è un modo molto migliore per farlo!

#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 potrebbe essere eccezionale sulla gamma, ma è ancora un po 'carente di precisione ...


4

C

Tutti odiamo gli overflow dei numeri interi, quindi utilizzeremo un piccolo esponente ne alcune conversioni in virgola mobile. Ma il teorema non reggerebbe 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");
}

Produzione:

Disproved for 2139095040, 2139095040, 2139095040, 42: yes

Disproved for 2139095040, 2139095040, 2139095040, 90: yes

In IEEE 754, il numero 2139095040, o 0x7F800000, rappresenta l'infinito positivo nei tipi a virgola mobile a precisione singola. Tutte le pow(...)chiamate restituiscono + Infinito e + Infinito è uguale a + Infinito. Un compito più semplice sarebbe confutare il teorema di Pitagora usando 0x7F800001 (Quiet NaN) che non è uguale a se stesso secondo lo standard.


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 è magico, lo sai.

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

E anche Wiles non è uno.

Javascript Numbernon è abbastanza grande.


2

T-SQL

Per confutare il teorema di questo Fermat, dobbiamo solo trovare un contro esempio. Sembra che fosse super pigro, e ci provò solo per una permutazione molto piccola. In effetti, non ci stava nemmeno provando. Ho trovato un esempio contatore in soli 0 <a, b, c <15 e 2 <e <15. Mi dispiace, sono un giocatore di golf nel cuore, quindi deselezionerò questo codice in seguito!

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)

Restituisce 1, nel senso che abbiamo trovato un contro esempio!

Il trucco è che mentre la prima e sembra un alias, in realtà è un modo subdolo di cambiare il tipo di dati di e da un int a un tipo a virgola mobile equivalente a un doppio. Quando arriviamo a 14 siamo oltre la precisione di un numero in virgola mobile in modo da poter aggiungere 1 ad esso e ancora non perdiamo nulla. La minificazione è una bella scusa per spiegare la mia doppia apparentemente sciocca dichiarazione di un alias di colonna nel rcte. Se non lo facessi, traboccarebbe molto prima che arrivassimo a 14 ^ 14.


1

JavaScript

Sembra che questo ragazzo stesse bene. A proposito di droghe se me lo chiedi. Dati i vincoli, non è possibile trovare un insieme di valori per i quali il teorema è vero.

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

alert(lhs === rhs);

Come in Java, l' ^operatore è l'operatore XOR bit a bit in JavaScript. Il modo corretto di calcolare la potenza di un numero è usare Math.pow.


2
Per Fermat, l'esponente ( n) deve essere >= 3.
ricorsivo il

Buon punto, il codice funziona comunque :)
thomaux,

0

Un altro controesempio BASIC

10 a = 858339
20 b = 2162359
30 c = 2162380
40 IF (a^10 + b^10) = c^10 THEN
50   PRINT "Fermat disproved!"
60 ENDIF
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.