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