“Disprove” Fermat'ın Son Teoremi [kapalı]


49

Bir program yazın, seçtiğiniz dilde, yani görünür başarıyla dair karşı bulmak için Fermat'ın Son Teoremi . Yani, a , b , c > 0 ve n > 2 tam sayılarını bulun , öyle ki bir n + b n = c n .

Tabii ki, Andrew Wiles'ın kanıtında bir kusur olmadığı sürece, gerçekten yapamazsınız. Güvenerek sahte demek istiyorum .

  • tamsayı taşması
  • kayan nokta yuvarlama hatası
  • tanımsız davranış
  • alışılmadık toplama, üs kullanma veya eşitlik tanımlarına sahip veri türleri
  • derleyici / tercüman hataları
  • veya bu çizgiler boyunca bir şey.

Sen değişkenlerin bazıları veya tamamı koda may a, b, c, veya n, ya da döngüler yaparak onları aramak gibi for a = 1 to MAX.

Bu bir kod golfü değil; akıllı ve zarif çözümler bulmak için bir yarışma.


Aslında, üs ya da üst olmak zorunda olan üs, üstelik hepsine sahip olanlar olabilir. Yani, 1 ^ 3 + 1 ^ 3 = 1 ^ 3 bu kadar basit.

2
@ Alıcı: 1³ + 1³ = 2; 1³ = 1; 2: 1
dan04

Yanıtlar:


57

J

Aslında, Fermat oldukça zayıfladı: a: 1 ise b, c veya n için aslında yanlış.

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

Belki de sadece belki, Fermat'ın öncelik kuralları kesinlikle sola doğru değildi.


19
+1 Kesinlikle sola doğru. Sadece soldan sağa okuyan insanlar için; sonuncusu için normal gösterimde olur1^(9 + (3^(9 = (42^9))))
seequ,

1
Sinsi, beynim eritmek üzereyken @ TheRare'nin yorumunu görene kadar erimekteydi
german_guy

3
Bu J'nin amaçlanan bir özelliği midir? Bu insanları gerçekten delirtecek türden bir şey.
qwr

2
@ qwr J'de, tüm istisnalar dışında tüm değerlendirme sağdan sola doğrudur. Kulağa garip geliyor ama aslında çok temiz.
seequ

1
@ dan04 Kesinlikle doğru konuşmuyor. 1^i.5olarak değerlendirir 1 1 1 1 1.
ɐɔıʇǝɥʇuʎs

36

TI-Temel

1782^12+1841^12=1922^12

Çıktı (doğru)

1


1
Bu bölümü çok sık gördüm, hiç farketmedim. Güzel yakalayış!
dom0

1
Bu cevap sadece TI-89-lezzet TI-Basic ile yazılan şekilde çalışır. Bir TI-84 + SE'de, kodun sözdizimi hatası vardır, çünkü bu TI-Basic sürümü boşluklara izin vermez. Ancak, boşlukları, yazıyı kaldırırsanız cevap hala eski bir hesap makinesinde çalışır 1782^12+1841^12=1922^12.
Rory O'Kane

1
TI-Basic kullanmak için +1, benim ilk programlama
dilimdi

2
@ThaneBrimhall Bu ironi, basit bir matematik probleminde başarısız olan bir hesap makinesi
qwr

35

Java

Bu Fermat adamı uyuyor olmalı. Denklemlere yüzlerce çözüm alıyorum. Excel formülümü yalnızca bir Java programına dönüştürdüm.

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

^Tipik düz metin üs alma aksine operatör aslında Java XOR demektir


Bunun neden işe yaradığına dair bir detaylandırma şansınız var mı?
Vality

20
@Vality: ^Java'da xor, güç değil.
marinus

3
Bu teknik olarak hemen hemen tüm C tabanlı dillerde çalışır
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;
}

İle derlendi clang++ -O3 -o fermat fermat.cpp, test edildi 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

Biz açıkçası a, b, c> 0 yani bulundu 3 + b 3 = c 3 (bu da n için çalışır = 4, 5, 6, ...).

A, b ve c'yi yazdırmak biraz zor olabilir ...


1
@ dan04: Hata unuttum ++in clang++.
Ventero

2
Bu arada, bu bir derleyici hatası değil. C (ve C ++) standardı burada val.utaşacak gibi herhangi bir şey yapmanıza izin verir (bunun uint32_tyerine farklı olurdu ). Ayrıca, bu kod aynı zamanda unionyanlış kullanır (standarda göre, bir alana yazamaz ve diğer alanı okuyamazsınız), ancak buna birçok derleyici tarafından izin verilir (belgelerine göre).
Konrad Borowski

3
Buna izin verilme nedeni, C ++ standardının bir bölümüdür: Bir for ifadesi için foritit ifadesinin dışında, * kütüphane G / Ç işlevlerine çağrı yapmaz, ve * yapmaz uçucu nesnelere erişme veya bunları değiştirme ve * hiçbir senkronizasyon işlemi yapmaz (1.10) veya atomik işlemlerin (Madde 29) uygulama tarafından sonlandırılacağı varsayılabilir.
dan04

3
Yani tam anlatım aslında bir sonraki taslakta standart kaldırılmıştır dan04 @, ABD içinde 38 bkz open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3196.htm - ama tabii, sadece oldu genelleştirilmiş. Bu, yazdırmanın a,b,c(veya bunun için herhangi bir şeyin) fermat()işlevini asla geri getirmemesinin nedenidir .
Ventero

8
Argh bunu gönderecektim. Kafası karışan herkes için: John Regehr'ın burada güzel bir açıklaması var .
Voo

13

Java

Teorem n = 3 için duruyor gibi görünüyor, fakat n = 4 için ters örnekler buldum:

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

Çıktı:

true

Açıklama:

Rakamlar küçük gibi görünse bile, 4. güce yükseltildiğinde taşarlar. Gerçekte, 64 4 + 496 4 = 528 4 - 2 34 , ancak int (32 bit) ile sınırlandığında 2 34 , 0 olur.


Bunu açıklayabilir misin?
Anubian Noob

@AnubianNoob bitti
aditsu

9

piton

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

Kim söylüyor c daha büyük olmalıdır bir ve b ?


2
TrueMath.pow, kayan noktalı sayıları döndürdüğü için basar ve bunlar doğru cevabı elde etmek için yeterli hassasiyete sahip değildir 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

Bu yaklaşım bir sürü farklı çözüm bulur. Örneğin:

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

Nasıl çalışır

İlk satır ~girişi yorumlamak için a ile başlamalıdır . Örneğin, 3 sayısı yerine, değişken Ndizgiyi içerir 3\n.
Birlikte 2 3 ?hesaplar ve 3 , 2 N ?ASCII kod 2 olan bir karakterin dizinini iter N(-1 bulunmayan için).
Bu şekilde, 43 N ?ve 82 N ?itme -1ve 51 N ?iter 0(51 ASCII karakter kodudur 3).
Zira -1 + 0 = -1, koşul karşılandı ve (43,51,82)bir "çözüm".


4

C

Elbette millet hepiniz karşı örnekler buluyorsunuz, tamsayı taşmalarıyla devam ediyorsunuz. Artı, c de yineleyerek gerçekten yavaş. Bu yapmak için çok daha iyi bir yol!

#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 aralıkta harika olabilir, ama hala hassaslıktan biraz eksik ...


4

C

Hepimiz tamsayı taşmasından nefret ediyoruz, bu nedenle küçük bir üs nve bazı kayan nokta dönüşümleri kullanacağız . Fakat yine de teorem beklemeyecekti 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");
}

Çıktı:

Disproved for 2139095040, 2139095040, 2139095040, 42: yes

Disproved for 2139095040, 2139095040, 2139095040, 90: yes

IEEE 754'te, 2139095040 veya 0x7F800000 sayısı, tek kesinlikli kayan nokta türlerinde pozitif sonsuzluğu temsil eder. Tüm pow(...)çağrılar + Infinity döndürür ve + Infinity + Infinity’e eşittir. Daha kolay bir görev, Pisagor teoremini, standarda göre kendisine eşit olmayan 0x7F800001 (Sessiz NaN) kullanarak çözmektir.


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 sihirdir, biliyorsun.

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

Ve ayrıca Wiles bir değil.

Javascript Numberyeterince büyük değil.


2

T-SQL

Bu Fermat adamı teoremini ispatlamak için bir karşı örnek bulmamız gerekiyor. Görünüşe göre süper tembeldi ve sadece küçük bir permütasyon için denedi. Aslında denemiyordu bile. Sadece 0 <a, b, c <15 ve 2 <e <15'te bir sayaç örneği buldum. Maalesef kalbinde bir golfçü olduğum için bu kodu daha sonra çözeceğim!

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)

İade 1, yani bir sayaç örneği bulduk!

İşin püf noktası, ilk e bir takma ad gibi görünmekle birlikte, aslında e'nin veri türünü bir int'den iki katına eşdeğer bir kayan nokta türüne değiştirmenin gizli bir yoludur. 14 yaşına geldiğimizde kayan nokta sayısının kesinliğinin ötesindeyiz, buna 1 ekleyebiliriz ve hala hiçbir şey kaybetmeyiz. Ufak tefek, rcte'deki bir sütun takma adının aptalca aptalca açıklamamı açıklamaktan hoş bir bahane. Bunu yapmasaydım, 14 ^ 14’e ulaşmadan çok önce taşardı.


1

JavaScript

Görünüşe göre bu adam iyi bir şeyler yapıyordu. Bana sorarsan ilaçlara. Kısıtlamalar göz önüne alındığında, teorem için geçerli olan hiçbir değer seti bulunamaz.

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

alert(lhs === rhs);

Java’da olduğu gibi, ^operatör JavaScript’teki bit cinsinden XOR operatörüdür. Bir sayının gücünü hesaplamanın doğru yolu Math.pow kullanmaktır.


2
Fermat için exponent ( n) olmalıdır >= 3.
özyinelemeli

İyi bir nokta, kod yine de çalışıyor :)
thomaux

0

Başka bir BASIC karşı örneği

10 a = 858339
20 b = 2162359
30 c = 2162380
40 IF (a^10 + b^10) = c^10 THEN
50   PRINT "Fermat disproved!"
60 ENDIF
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.