Fermats letzter Satz „widerlegen“ [geschlossen]


49

Schreiben Sie ein Programm in der Sprache Ihrer Wahl, das ein Gegenbeispiel zu Fermats letztem Satz zu finden scheint . Das heißt, finde ganze Zahlen a , b , c > 0 und n > 2, so dass a n + b n = c n ist .

Natürlich kann man das nicht wirklich tun, es sei denn, Andrew Wiles 'Beweis weist einen Fehler auf. Ich meine, fälschen Sie es , indem Sie sich darauf verlassen

  • Integer-Überlauf
  • Gleitkomma-Rundungsfehler
  • undefiniertes Verhalten
  • Datentypen mit ungewöhnlichen Definitionen für Addition, Potenzierung oder Gleichheit
  • Compiler / Interpreter-Fehler
  • oder etwas in diese Richtung.

Sie können hart Code einige oder alle Variablen a, b, c, oder n, oder nach ihnen suchen durch Schleifen wie tun for a = 1 to MAX.

Dies ist kein Code-Golf; Es ist ein Wettbewerb, um clevere und subtile Lösungen zu finden.


Tatsächlich kann man sie alle haben, außer dem Exponenten, der 3 oder höher sein muss. Also ist 1 ^ 3 + 1 ^ 3 = 1 ^ 3 so einfach.

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

Antworten:


57

J

Eigentlich hat Fermat einen ziemlichen Fehler gemacht: Es ist tatsächlich falsch für jedes b, c oder n, wenn a 1 ist:

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

Vielleicht, vielleicht, waren Fermats Vorrangregeln nicht von rechts nach links.


19
+1 Genau genommen von rechts nach links. Nur für Leute, die von links nach rechts lesen; Die normale Schreibweise für die letzte wäre1^(9 + (3^(9 = (42^9))))
siehe dazu

1
Sneaky, mein Gehirn wollte schmelzen, bis ich @ TheRares Kommentar sah
german_guy

3
Ist dies ein beabsichtigtes Merkmal von J? Dies ist die Art von Dingen, die die Leute wirklich wahnsinnig machen würden.
QWR

2
@qwr In J erfolgt die Auswertung mit einigen Ausnahmen von rechts nach links. Es klingt komisch, ist aber eigentlich ziemlich ordentlich.
Siehe auch

1
@ dan04 Eigentlich nicht wahr. 1^i.5bewertet zu1 1 1 1 1 .
1.

36

TI-Basic

1782^12+1841^12=1922^12

Ausgabe (wahr)

1


1
Ich habe diese Episode so oft gesehen, das habe ich nie bemerkt. Schöner Fang!
Dom0

1
Diese Antwort funktioniert nur mit TI-89-TI-Basic. Auf einem TI-84 + SE weist der Code einen Syntaxfehler auf, da diese Version von TI-Basic keine Leerzeichen zulässt. Aber die Antwort funktioniert immer noch auf einem älteren Rechner, wenn Sie Leerzeichen entfernen und schreiben 1782^12+1841^12=1922^12.
Rory O'Kane

1
+1 für die Verwendung von TI-Basic, es war meine erste Programmiersprache :)
Kik

2
@ThaneBrimhall Das ist die Ironie, ein Taschenrechner, der ein einfaches mathematisches Problem nicht
löst

35

Java

Dieser Fermat muss geschlafen haben. Ich bekomme Hunderte von Lösungen für die Gleichungen. Ich habe lediglich meine Excel-Formel in ein Java-Programm konvertiert.

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

Der ^Operator bedeutet tatsächlich XOR in Java, im Gegensatz zur Potenzierung in typischem Klartext


Gibt es eine Chance für eine Ausarbeitung, warum dies funktioniert?
Vality

20
@Vality: ^In Java ist xor keine Macht.
Marinus

3
Dies funktioniert technisch auf fast allen C-basierten Sprachen
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;
}

Kompiliert mit clang++ -O3 -o fermat fermat.cpp, getestet mit 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

Wir haben offensichtlich a, b, c> 0 gefunden, so dass a 3 + b 3 = c 3 (dies funktioniert auch für n = 4, 5, 6, ...).

Das Drucken von a, b und c könnte sich jedoch als schwierig erweisen ...


1
@ dan04: Hoppla, hab das ++in vergessen clang++.
Ventero

2
Dies ist übrigens kein Compiler-Bug. Der C (und C ++) Standard erlaubt hier alles, val.uwas überlaufen kann (es wäre anders, wenn es uint32_tstattdessen wäre). Außerdem wird dieser Code auch unionfalsch verwendet (standardmäßig können Sie nicht in ein Feld schreiben und das andere Feld lesen), aber dies wird von vielen Compilern (gemäß ihrer Dokumentation) zugelassen.
Konrad Borowski

3
Der Grund, warum dies zulässig ist, ist ein Abschnitt des C ++ - Standards, der besagt: Eine Schleife, die außerhalb der for-init-Anweisung im Fall einer for-Anweisung * keine Aufrufe an Bibliotheks-E / A-Funktionen vornimmt und * dies nicht tut auf flüchtige Objekte zugreifen oder diese ändern und * keine Synchronisationsoperationen (1.10) oder atomare Operationen (Klausel 29) ausführt, kann von der Implementierung angenommen werden, dass sie beendet werden.
Dan04

3
@ dan04 Dieser genaue Wortlaut wurde in einem späteren Entwurf tatsächlich aus dem Standard entfernt, siehe US 38 in open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3196.htm - aber natürlich nur verallgemeinert. Dies ist der Grund, warum das Ausdrucken a,b,c(oder was auch immer) fermat()der Funktion dazu führt, dass sie niemals zurückkehrt.
Ventero

8
Argh, ich wollte das so posten. Für alle , die verwirrt sind: John Regehr hat eine schöne Erklärung hier .
Voo

13

Java

Es sieht so aus, als ob der Satz für n = 3 gilt, aber ich habe Gegenbeispiele für n = 4 gefunden:

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

Ausgabe:

true

Erläuterung:

Selbst wenn die Zahlen klein erscheinen, laufen sie über, wenn sie auf die 4. Potenz angehoben werden. In Wirklichkeit ist 64 4 + 496 4 = 528 4 - 2 34 , aber 2 34 wird 0, wenn es auf int (32 Bits) beschränkt ist.


Kannst du das erklären?
Anubian Noob

@ AnubianNoob fertig
Aditsu

9

Python

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

Wer sagt, dass c größer sein muss als a und b ?


2
Es wird gedruckt, Trueweil math.pow Gleitkommazahlen zurückgibt und diese nicht genau genug sind, um die richtige Antwort zu erhalten 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

Dieser Ansatz findet eine Reihe verschiedener Lösungen. Zum Beispiel:

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

Wie es funktioniert

Die erste Zeile sollte mit a beginnen ~, um die Eingabe zu interpretieren. Anstelle von zB der Nummer 3 Nenthält die Variable den String 3\n.
Bei der 2 3 ?Berechnung von 3 wird 2 N ?der Index eines Zeichens mit dem ASCII-Code 2 in N(-1 für nicht gefunden) verschoben.
Auf diese Weise 43 N ?und 82 N ?Push -1und 51 N ?Stösse 0(51 ist der ASCII - Zeichencode 3).
Da -1 + 0 = -1ist die Bedingung erfüllt und (43,51,82)eine "Lösung".


4

C

Natürlich findet ihr alle Gegenbeispiele, ihr bekommt immer wieder Integer-Überläufe. Außerdem sind Sie sehr langsam, wenn Sie auch c durchlaufen. Dies ist ein viel besserer Weg, es zu tun!

#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 mag auf dem Gebiet großartig sein, aber es fehlt immer noch ein bisschen an Präzision ...


4

C

Wir alle hassen Integer-Überläufe, daher verwenden wir einen kleinen Exponenten nund einige Gleitkommakonvertierungen. Aber dennoch würde der Satz nicht gelten 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");
}

Ausgabe:

Disproved for 2139095040, 2139095040, 2139095040, 42: yes

Disproved for 2139095040, 2139095040, 2139095040, 90: yes

In IEEE 754 steht die Nummer 2139095040 oder 0x7F800000 für eine positive Unendlichkeit bei Gleitkommatypen mit einfacher Genauigkeit. Alle pow(...)Aufrufe würden + Infinity zurückgeben, und + Infinity entspricht + Infinity. Eine einfachere Aufgabe wäre es, den Satz von Pythagoras zu widerlegen, indem 0x7F800001 (Quiet NaN) verwendet wird, das nach dem Standard nicht mit sich selbst übereinstimmt.


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 ist Magie, weißt du?

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

Und auch Wiles ist keiner.

Javascript Numberist nicht groß genug.


2

T-SQL

Um den Satz von Fermat zu widerlegen, müssen wir nur ein Gegenbeispiel finden. Es scheint, er war super faul und versuchte es nur für eine wirklich kleine Permutation. Tatsächlich versuchte er es nicht einmal. Ich habe ein Gegenbeispiel in nur 0 <a, b, c <15 und 2 <e <15 gefunden. Tut mir leid, dass ich im Herzen ein Golfer bin, also werde ich diesen Code später wieder entfernen!

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)

Gibt 1 zurück, was bedeutet, dass wir ein Gegenbeispiel gefunden haben!

Der Trick besteht darin, dass das erste e zwar wie ein Alias ​​aussieht, es jedoch eine raffinierte Möglichkeit ist, den Datentyp von e von einem int-Wert in einen Gleitkomma-Wert zu ändern, der einem double-Wert entspricht. Mit 14 ist die Genauigkeit einer Gleitkommazahl noch nicht erreicht, sodass wir 1 hinzufügen können und trotzdem nichts verlieren. Die Verkleinerung ist eine nette Ausrede, um meine scheinbar alberne doppelte Deklaration eines Spaltenalias im RCTE zu erklären. Wenn ich das nicht täte, würde es überlaufen, lange bevor wir 14 ^ 14 haben.


1

JavaScript

Es scheint, dass dieser Kerl auf etwas in Ordnung war. Auf Drogen, wenn du mich fragst. Angesichts der Einschränkungen kann kein Satz von Werten gefunden werden, für den der Satz gilt.

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

alert(lhs === rhs);

Wie in Java ist der ^Operator der bitweise XOR-Operator in JavaScript. Die korrekte Methode zur Berechnung der Potenz einer Zahl ist die Verwendung von Math.pow.


2
Für Fermat muss der Exponent ( n) sein >= 3.
rekursiver

Guter Punkt, der Code funktioniert immer noch :)
thomaux

0

Ein weiteres BASIC-Gegenbeispiel

10 a = 858339
20 b = 2162359
30 c = 2162380
40 IF (a^10 + b^10) = c^10 THEN
50   PRINT "Fermat disproved!"
60 ENDIF
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.