「反証」フェルマーの最後の定理[閉じた]


49

Fermatの最終定理の反例をうまく見つけたと思われるプログラムを、選択した言語で記述します。つまり、a n + b n = c nであるような整数abc > 0およびn > 2を見つけます。

もちろん、Andrew Wilesの証拠に欠陥がない限り、あなたは本当にそれをすることはできませ。に頼ることによって、私はそれを偽造することを意味します

  • 整数オーバーフロー
  • 浮動小数点丸めエラー
  • 未定義の動作
  • 加算、べき乗、または等式の異常な定義を持つデータ型
  • コンパイラ/インタープリターのバグ
  • またはそれらの線に沿って何か。

あなたは、ハードコードは、一部またはすべての変数かもしれないabc、またはn、またはのようなループを実行して、それらを検索for a = 1 to MAX

これはコードゴルフではありません。巧妙で微妙な解決策を見つけるコンテストです。


実際には、3以上でなければならない指数のほかに、すべてを1つ持つことができます。そのため、1 ^ 3 + 1 ^ 3 = 1 ^ 3は簡単です。

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

回答:


57

J

実際、フェルマーはかなり失敗しました:aが1の場合、b、c、またはnについては実際に間違っています。

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

たぶん、多分、Fermatの優先ルールは厳密に右から左ではなかった。


19
+1厳密に右から左へ確かに。左から右に読む人のためだけに。最後の1つの通常の表記は1^(9 + (3^(9 = (42^9))))
seequ 14年

1
卑劣な、@ TheRareのコメントを見るまで私の脳は溶けそうだった
german_guy 14年

3
これはJの意図された機能ですか?これは本当に人々を狂わせるようなものです。
qwr 14年

2
@qwr Jでは、いくつかの例外を除き、すべての評価は右から左に行われます。奇妙に聞こえますが、実際にはかなりきれいです。
seequ 14年

1
@ dan04厳密には真実ではありません。1^i.5に評価され1 1 1 1 1ます。
ɐɔıʇǝɥʇuʎs

36

TI-ベーシック

1782^12+1841^12=1922^12

出力(true)

1


1
私はそのエピソードを頻繁に見ましたが、それに気付くことはありませんでした。ナイスキャッチ!
dom0

1
この回答は、TI-89-flavor TI-Basicで書かれている場合にのみ機能します。TI-84 + SEでは、TI-Basicのバージョンではスペースが許可されないため、コードに構文エラーがあります。しかし、スペースを削除して書くと、答えは古い計算機でも機能します1782^12+1841^12=1922^12
ロリーオケイン14年

1
TI-Basicを使用して+1、それは私の最初のプログラミング言語でした:)
Kik

2
それは皮肉だ、簡単な計算問題を失敗電卓@ThaneBrimhall
QWR

35

Java

このフェルマーの男は寝ていたに違いない。方程式の数百の解を得る。Excelの数式を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));
    }
}

^典型的なプレーンテキストで累乗とは対照的に、オペレータは、実際には、JavaでXORを意味し、


これが機能する理由について詳しく説明する機会はありますか?
バリティ14年

20
@Vality:^Javaでは、xorはパワーではありません。
マリヌス14年

3
これは技術的にはほぼすべての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;
}

でコンパイルclang++ -O3 -o fermat fermat.cpp、テスト済み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

明らかにa、b、c> 0であるため、a 3 + b 3 = c 3です(これはn = 4、5、6、...でも機能します)。

a、b、cの印刷は少し難しいかもしれませんが...


1
@ dan04:おっと、忘れまし++clang++
ヴェンテロ14年

2
ところで、これはコンパイラのバグではありません。C(およびC ++)標準では、val.uオーバーフローの可能性があるため、ここで何でもできます(uint32_t代わりになる場合は異なります)。また、このコードunionは誤った方法で使用します(標準に従って、1つのフィールドに書き込み、他のフィールドを読み取ることはできません)が、これは多くのコンパイラーで許可されています(ドキュメントによる)。
コンラッド

3
これが許可されている理由は、C ++標準のセクションです。forステートメントの場合はfor-init-statementの外側で、*はライブラリI / O関数を呼び出さず、*はしないループです。揮発性オブジェクトにアクセスまたは変更し、*同期操作(1.10)を実行しないか、アトミック操作(29節)が実装によって終了すると見なされる場合があります。
dan04

3
@ dan04正確な言葉遣いは後のドラフトで標準から実際に削除されました。open - std.org/ jtc1 / sc22 / wg21 / docs / papers / 2010 / n3196.htmのUS 38を参照してください-しかし、もちろん一般化された。これが、印刷a,b,c(またはそのことは何でも)でfermat()関数が戻らない理由です。
Ventero

8
ああ、それを投稿するつもりだった。混乱している人のために:John Regehrがここでいい説明をしています
Voo 14年

13

Java

定理はn = 3に当てはまるように見えますが、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));
    }
}

出力:

true

説明:

数字が小さいように見えても、4乗するとオーバーフローします。実際には、64 4 + 496 4 = 528 4 - 2 34が、2 34は、 INT(32ビット)に制限されたときに0になります。


これを説明できますか?
アヌビアヌーブ14

@AnubianNoob完了
aditsu 14年

9

Python

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

cabより大きくなければならないというのは誰ですか?


2
Truemath.powが浮動小数点数を返し、これらが正しい答えを得るのに十分な精度を持っていないために出力されますFalse
カーニグ14年

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

このアプローチは、さまざまなソリューションを見つけます。例えば:

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

使い方

最初の行は~、入力を解釈するためにaで始まる必要があります。たとえば、数値3の代わりに、変数Nには文字列が含まれます3\n
ながら2 3 ?計算32 N ?でASCIIコード2の文字のインデックスを押すN(-1見つからないため)。
このように43 N ?82 N ?プッシュ-151 N ?プッシュ0(51 はのASCII文字コードです3)。
なので-1 + 0 = -1、条件は満たされ(43,51,82)、「解決策」です。


4

C

もちろん、皆さんは反例を見つけているので、整数のオーバーフローを続けています。さらに、cを繰り返し処理することで、本当に遅くなっています。これは、はるかに優れた方法です。

#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 範囲で素晴らしいかもしれませんが、それはまだ精度が少し欠けています...


4

C

私たちはすべて整数オーバーフローを嫌うので、小さな指数nといくつかの浮動小数点変換を使用します。しかし、それでも定理は成り立たないでしょう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");
}

出力:

Disproved for 2139095040, 2139095040, 2139095040, 42: yes

Disproved for 2139095040, 2139095040, 2139095040, 90: yes

IEEE 754では、数値2139095040または0x7F800000は、単精度浮動小数点型の正の無限大を表します。すべてのpow(...)呼び出しは+ Infinityを返し、+ Infinityは+ Infinityに等しくなります。より簡単なタスクは、標準に従ってそれ自体と等しくない0x7F800001(Quiet NaN)を使用してピタゴラスの定理を反証することです。


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は魔法です。

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

また、ウィルズもそうではありません。

Javascript Numberは十分な大きさではありません。


2

T-SQL

このフェルマーの男の定理を反証するには、反例を見つける必要があります。彼はとても怠け者で、本当に小さな順列のためだけに試したようです。実際、彼は試してさえいませんでした。ちょうど0 <a、b、c <15および2 <e <15で反例が見つかりました。申し訳ありませんが、私は心のゴルファーなので、このコードを後で確認します。

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)

1を返します。これは、反例を見つけたことを意味します。

トリックは、最初のeはエイリアスのように見えますが、実際にはeのデータ型をintからdoubleに相当する浮動小数点型に変更する卑劣な方法です。14に達した時点で、浮動小数点数の精度を超えているため、1を加算しても何も失われません。縮小は、rcteの列エイリアスの、一見愚かに見える二重宣言を説明する良い言い訳です。これを行わなかった場合、14 ^ 14に到達するずっと前にオーバーフローしました。


1

JavaScript

この男は大丈夫なように見えた。あなたが私に尋ねたら薬に。制約を考えると、定理が当てはまる値のセットは見つかりません。

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

alert(lhs === rhs);

Javaと同様に、^演算子はJavaScriptのビット単位のXOR演算子です。数値のべき乗を計算する正しい方法は、Math.powを使用することです。


2
Fermatの場合、exponent(n)はでなければなりません>= 3
再帰的14年

良い点は、コードはまだ動作します:)
thomaux 14年

0

別の基本的な反例

10 a = 858339
20 b = 2162359
30 c = 2162380
40 IF (a^10 + b^10) = c^10 THEN
50   PRINT "Fermat disproved!"
60 ENDIF
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.