페르마의 마지막 정리를“반증”[폐쇄]


49

Fermat 's Last Theorem에 대한 반례를 성공적으로 찾은 것처럼 선택한 언어로 프로그램을 작성하십시오 . 즉, 정수를 찾을 수있다 , B를 , C > 0, N > 2 등이 , N + B N = C의 N .

물론 앤드류 와일즈의 증거에 결함이 없다면 실제로 는 할 수 없습니다 . 나는 의지하여 가짜를 의미 합니다 .

  • 정수 오버플로
  • 부동 소수점 반올림 오류
  • 정의되지 않은 행동
  • 덧셈, 지수 또는 평등에 대한 특이한 정의가있는 데이터 유형
  • 컴파일러 / 통역사 버그
  • 또는 그 라인을 따라 뭔가.

당신은 변수의 일부 또는 전부가 하드 코딩 할 수있다 a, b, c, 또는 n, 또는 루프를 수행하여이를 검색이 좋아 for a = 1 to MAX.

이것은 코드 골프가 아닙니다. 영리하고 미묘한 해결책을 찾기위한 콘테스트입니다.


실제로, 지수 이외의 모든 것을 3 이상으로 가질 수 있습니다. 따라서 1 ^ 3 + 1 ^ 3 = 1 ^ 3은 간단합니다.

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

답변:


57

제이

실제로 Fermat는 실수를 범했습니다. 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^(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.
ɐɔıʇǝɥʇ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.
Rory O'Kane 2016 년

1
TI-Basic을 사용하는 +1, 그것은 나의 첫 번째 프로그래밍 언어였습니다 :)
Kik

2
@ThaneBrimhall 그것은 간단한 수학 문제에 실패한 아이러니입니다.
qwr

35

자바

이 Fermat 사람은 자고 있었을 것입니다. 방정식에 대한 수백 가지 솔루션을 얻습니다. 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을 의미한다


왜 이것이 작동하는지 자세히 설명 할 수 있습니까?
Vality

20
@Vality : ^Java에서 xor는 전원이 아닙니다.
marinus 2016 년

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++.
Ventero

2
그건 그렇고, 이것은 컴파일러 버그가 아닙니다. C (및 C ++) 표준은 val.u오버플 로 가 발생할 수있는 것처럼 여기에서 무엇이든 할 수 있습니다 ( uint32_t대신 경우 다를 수 있음 ). 또한이 코드는 union표준에 따라 하나의 필드에 쓰거나 다른 필드를 읽을 수없는 잘못된 방식으로 도 사용 되지만 많은 컴파일러 (문서에 따라)에서 허용됩니다.
Konrad Borowski 2016 년

3
이것이 허용되는 이유는 다음과 같이 말하는 C ++ 표준의 섹션입니다. 휘발성 객체에 액세스 또는 수정하고, *는 동기화 동작 (1.10)을 수행하지 않거나 원자 동작 (원인 29)은 구현에 의해 종료 될 수있다.
dan04

3
@ dan04 정확한 초안은 차후 초안에서 실제로 표준에서 제거되었습니다. open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3196.htm의 미국 38 참조 – 물론, 그것은 단지 일반화. 이것이 인쇄 a,b,c(또는 그 문제에 대해 무엇이든) fermat()가 함수를 절대 반환하지 않는 이유입니다.
Ventero

8
아아, 나는 그 것을 게시하려고했습니다. 혼란스러워하는 사람에게는 John Regehr가 여기에 대한 좋은 설명이 있습니다 .
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) (32 비트) int로 한정 할 때 0이된다.


이것을 설명 할 수 있습니까?
Anubian Noob 2016

@AnubianNoob 완료
aditsu

9

파이썬

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

누가 cab 보다 커야 한다고 누가 말 합니까?


2
Truemath.pow가 부동 소수점 숫자를 리턴하기 때문에 인쇄 되며, 정답을 얻기에 충분한 정밀도가 없습니다 False.
kernigh 2016 년

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 ?푸시 -151 N ?밀어 0(51의 ASCII 문자 코드이다 3).
이후 -1 + 0 = -1조건이 충족되고 (43,51,82)"솔루션"입니다.


4

물론 여러분은 모두 반례를 찾고 있습니다. 정수 오버플로가 계속 발생합니다. 또한 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

우리는 모두 정수 오버플로를 싫어하므로 작은 지수 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.

또한 와일즈도 아닙니다.

자바 스크립트 Number가 충분하지 않습니다.


2

T-SQL

이 Fermat 남자의 정리를 반증하기 위해, 우리는 반례를 찾아야합니다. 그는 매우 게으른 것처럼 보였고 실제로 작은 순열에만 시도했습니다. 사실, 그는 시도조차하지 않았다. 나는 0 <a, b, c <15 and 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

자바 스크립트

이 녀석이 문제가있는 것 같습니다. 당신이 나에게 요청하면 약물에. 구속 조건이 주어지면 정리가 참인 값 세트를 찾을 수 없습니다.

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의 경우 지수 ( n)는이어야 >= 3합니다.
재귀

좋은 점, 코드는 여전히 작동하지만 :)
thomaux

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.