ทฤษฎีบทสุดท้ายของแฟร์มาต์“ หักล้าง” [ปิด]


49

เขียนโปรแกรมในภาษาที่คุณเลือกที่จะปรากฏขึ้นที่จะประสบความสำเร็จพบ counterexample กับทฤษฎีบทสุดท้ายของแฟร์มา นั่นคือหาจำนวนเต็ม, , > 0 และn > 2 ดังกล่าวที่n + B n c = n

แน่นอนคุณไม่สามารถทำได้จริง ๆเว้นแต่จะมีข้อบกพร่องในการพิสูจน์ของ Andrew Wiles ฉันหมายถึงของปลอมโดยอาศัย

  • ล้นจำนวนเต็ม
  • ข้อผิดพลาดในการปัดเศษทศนิยม
  • พฤติกรรมที่ไม่ได้กำหนด
  • ชนิดข้อมูลที่มีคำจำกัดความที่ผิดปกติของการเพิ่มการยกกำลังหรือความเท่าเทียมกัน
  • ข้อผิดพลาดของคอมไพเลอร์ / ล่าม
  • หรือบางสิ่งบางอย่างตามสายเหล่านั้น

คุณอาจจะยากรหัสบางส่วนหรือทั้งหมดของตัวแปรa, b, cหรือหรือค้นหาได้โดยการทำลูปเช่นnfor a = 1 to MAX

นี่ไม่ใช่รหัสกอล์ฟ เป็นการประกวดเพื่อค้นหาวิธีแก้ปัญหาที่ชาญฉลาดและละเอียดอ่อน


อันที่จริงคุณสามารถมีวัตถุเป็นของพวกเขาทั้งหมดนอกเหนือจากเลขชี้กำลังซึ่งจะต้องมี 3 หรือสูงกว่า ดังนั้น 1 ^ 3 + 1 ^ 3 = 1 ^ 3 มันง่ายมาก

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

คำตอบ:


57

J

อันที่จริงแฟร์มาต์ทำผิดพลาดค่อนข้าง: จริง ๆ แล้วมันผิดสำหรับ b, c หรือ n ใด ๆ ถ้าเป็น 1:

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

บางทีอาจเป็นไปได้ว่ากฎของลำดับความสำคัญของแฟร์มาต์ไม่ได้ไปจากขวา


19
+1 จากขวาไปซ้ายอย่างเคร่งครัด สำหรับคนที่อ่านจากซ้ายไปขวา สัญกรณ์ปกติสำหรับตัวสุดท้ายจะเป็น1^(9 + (3^(9 = (42^9))))
seequ

1
ส่อเสียดสมองของฉันกำลังจะละลายจนกว่าฉันจะเห็นความคิดเห็นของ @ TheRare
german_guy

3
นี่เป็นคุณสมบัติที่ตั้งใจไว้ของ J หรือไม่? นี่คือสิ่งที่จะผลักดันคนบ้า
qwr

2
@qwr ใน J การประเมินทั้งหมดมาจากขวาไปซ้ายโดยมีข้อยกเว้นบางประการ ฟังดูแปลก ๆ แต่จริงๆแล้วค่อนข้างเรียบร้อย
seequ

1
@ dan04 พูดไม่จริงอย่างเคร่งครัด ประเมิน1^i.5 1 1 1 1 1
Julıʇǝɥʇuʎs

36

TI-Basic

1782^12+1841^12=1922^12

เอาท์พุท (จริง)

1


1
ฉันเห็นตอนนั้นบ่อยครั้งไม่เคยสังเกตเลย รับได้สวย!
dom0

1
คำตอบนี้ใช้ได้ผลตามที่เขียนด้วย TI-89- รสชาติ TI-Basic เท่านั้น บน TI-84 + SE รหัสมีข้อผิดพลาดทางไวยากรณ์เนื่องจากรุ่นของ TI-Basic นั้นไม่อนุญาตให้มีช่องว่าง 1782^12+1841^12=1922^12แต่คำตอบยังคงทำงานบนเครื่องคิดเลขเก่าถ้าคุณลบช่องว่างการเขียน
Rory O'Kane

1
+1 สำหรับใช้ TI-พื้นฐานมันเป็นภาษาเขียนโปรแกรมครั้งแรกของฉัน :)
กิ๊ก

2
@ThaneBrimhall นั่นคือการประชด, เครื่องคิดเลขล้มเหลวปัญหาคณิตศาสตร์ที่เรียบง่าย
qwr

35

ชวา

คนที่แต่งตัวประหลาดแฟร์มาต์คนนี้ต้องนอนแล้ว ฉันได้คำตอบเป็นร้อยสำหรับสมการ ฉันแค่แปลงสูตร 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));
    }
}

ตัว^ดำเนินการจริงหมายถึง XOR ใน Java ซึ่งตรงข้ามกับการยกกำลังในข้อความธรรมดาทั่วไป


โอกาสใด ๆ ในการทำอย่างละเอียดว่าทำไมถึงได้ผล?
Vality

20
@Vality: ^ใน Java คือ xor ไม่ใช่กำลัง
marinus

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 ดังนั้น3 + b 3 = c 3 (สิ่งนี้ใช้ได้สำหรับ n = 4, 5, 6, ... )

การพิมพ์ a, b และ c อาจพิสูจน์ได้ยากสักหน่อยแม้ว่า ...


1
@ dan04: โอ๊ะลืมใน++ clang++
Ventero

2
อย่างไรก็ตามนี่ไม่ใช่ข้อผิดพลาดของคอมไพเลอร์ มาตรฐาน C (และ C ++) อนุญาตให้ทำอะไรที่นี่ได้เช่นเดียวกับที่มากval.uเกินไป (มันจะแตกต่างกันถ้ามันจะถูกuint32_tแทนที่) นอกจากนี้รหัสนี้ยังใช้unionในวิธีที่ไม่ถูกต้อง (ตามมาตรฐานคุณไม่สามารถเขียนลงในช่องหนึ่งและอ่านอีกช่องหนึ่งได้) แต่ก็อนุญาตโดยคอมไพเลอร์หลายตัว (ตามเอกสารประกอบ)
Konrad Borowski

3
เหตุผลนี้ได้รับอนุญาตเป็นส่วนหนึ่งของมาตรฐาน C ++ ที่ระบุว่า: วนรอบนอกคำสั่ง for-init-statement ในกรณีของคำสั่ง for, * ทำให้ไม่มีการเรียกไปยังฟังก์ชั่นไลบรารี I / O และ * ไม่ การเข้าถึงหรือแก้ไขวัตถุที่ระเหยได้และ * ไม่มีการดำเนินการซิงโครไนซ์ (1.10) หรือการดำเนินการปรมาณู (ข้อ 29) อาจถูกสันนิษฐานโดยการนำไปใช้เพื่อยุติ
dan04

3
@ dan04 ถ้อยคำที่แท้จริงนั้นถูกลบออกจากมาตรฐานในแบบร่างในภายหลังโปรดดู US 38 ในopen-std.org/jtc1/sc22/wg21/docs/papers/2010/n3196.htm - แต่แน่นอนว่ามันเป็นเพียง ทั่วไป นี่คือเหตุผลที่ทำให้การพิมพ์a,b,c(หรืออะไรก็ตามสำหรับเรื่องนั้น) fermat()ทำให้ฟังก์ชั่นไม่กลับมา
Ventero

8
Argh ฉันจะโพสต์นั้น สำหรับใครที่สับสน: จอห์นเรเจหยรมีคำอธิบายที่ดีที่นี่
Voo

13

ชวา

ดูเหมือนว่าทฤษฎีบทจะมีค่าสำหรับ 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กลายเป็น 0 เมื่อ จำกัด ไว้ที่ int (32 บิต)


คุณอธิบายได้ไหม
Anubian Noob

@AnubianNoob ทำได้แล้ว
aditsu

9

หลาม

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

ที่บอกว่าต้องมากกว่าและ ?


2
มันพิมพ์Trueเพราะ Math.pow 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

วิธีการนี้ค้นหาโซลูชันที่แตกต่างกันมากมาย ตัวอย่างเช่น:

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

มันทำงานอย่างไร

บรรทัดแรกควรเริ่มต้นด้วย a ~เพื่อตีความอินพุต แทนที่จะเป็นเช่นตัวแปรหมายเลข 3 Nมีสตริง3\nอยู่
ในขณะที่2 3 ?คำนวณ3ให้2 N ?กดดัชนีของอักขระด้วยรหัส ASCII 2 ในN(ไม่พบ -1)
วิธีนี้43 N ?และ82 N ?ผลักดัน-1และ51 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

จาวาสคริ

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. ขออภัยฉันเป็นนักกอล์ฟที่ใจดังนั้นฉันจะ ungolf รหัสนี้ในภายหลัง!

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 จาก int เป็นชนิดจุดลอยเทียบเท่ากับสองครั้ง ตามเวลาที่เราได้ถึง 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 ตัว^ดำเนินการเป็นตัวดำเนินการ XOR แบบบิตใน JavaScript วิธีที่ถูกต้องในการคำนวณกำลังของตัวเลขคือใช้ Math.pow


2
สำหรับแฟร์มาต์, สัญลักษณ์ ( n) >= 3จะต้องมีการ
เรียกซ้ำ

จุดดีรหัสยังคงทำงานแม้ว่า :)
thomaux

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.