“Disprove” Fermat's Last Theorem

49

6

Write a program, in the language of your choice, that appears to successfully find a counterexample to Fermat's Last Theorem. That is, find integers a, b, c > 0 and n > 2 such that an + bn = cn.

Of course, you can't really do it, unless there's a flaw in Andrew Wiles' proof. I mean fake it, by relying on

  • integer overflow
  • floating-point rounding error
  • undefined behavior
  • data types with unusual definitions of addition, exponentiation, or equality
  • compiler/interpreter bugs
  • or something along those lines.

You may hard-code some or all of the variables a, b, c, or n, or search for them by doing loops like for a = 1 to MAX.

This isn't a code golf; it's a contest to find clever and subtle solutions.

dan04

Posted 2014-06-27T23:27:22.877

Reputation: 6 319

Question was closed 2016-02-10T19:53:46.443

actually, you can have ones as all of them besides the exponent, which has to be 3 or higher. So, 1^3+1^3=1^3 its that simple. – None – 2014-10-23T02:21:45.280

2@Siver: 1³+1³=2; 1³=1; 2≠1 – dan04 – 2014-10-23T03:52:41.880

Answers

57

J

Actually, Fermat did make quite a blunder: It's actually wrong for any b, c or n if a is 1:

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

Maybe just maybe, Fermat's precedence rules weren't strictly right to left.

jpjacobs

Posted 2014-06-27T23:27:22.877

Reputation: 3 440

19+1 Strictly right to left indeed. Just for people who read left to right; normal notation for the last one would be 1^(9 + (3^(9 = (42^9)))) – seequ – 2014-06-28T15:41:31.543

Ah...so any expression that starts with 1^ evaluates to 1. – dan04 – 2014-06-28T16:22:40.370

1Sneaky, my brain was about to melt until I saw @TheRare's comment – german_guy – 2014-06-29T18:37:08.357

@german_guy Glad to be of help. – seequ – 2014-06-29T18:55:24.927

3Is this an intended feature of J? This is the kind of thing that would really drive people insane. – qwr – 2014-06-30T06:20:38.337

2@qwr In J, all evaluation is from right to left, with some exceptions. It sounds weird but is actually pretty neat. – seequ – 2014-06-30T07:09:52.217

1@dan04 Not strictly speaking true. 1^i.5 evaluates to 1 1 1 1 1. – ɐɔıʇǝɥʇuʎs – 2014-07-01T20:20:24.587

36

TI-Basic

1782^12+1841^12=1922^12

Output (true)

1

qwr

Posted 2014-06-27T23:27:22.877

Reputation: 8 929

@dan04 What is the reference here? – seequ – 2014-06-28T15:37:19.997

1I saw that episode so often, never noticed that. Nice catch! – dom0 – 2014-06-29T14:57:54.777

1This answer only works as written with TI-89-flavor TI-Basic. On a TI-84+ SE, the code has a syntax error, because that version of TI-Basic does not allow spaces. But the answer still works on an older calculator if you remove spaces, writing 1782^12+1841^12=1922^12. – Rory O'Kane – 2014-06-29T21:59:02.217

If I evaluate 1782^12+1841^12 or 1922^12 separately, each outputs “2.541210259e39”, suggesting a floating-point rounding error. But if I try to view the hidden significant digits, fPart((1782^12+1841^12)/10^33) outputs .2586147, while fPart((1922^12)/10^33) outputs .2593147. I’m confused how the calculator made the rounding mistake for the large numbers, yet outputs different numbers when the large numbers are re-divided. – Rory O'Kane – 2014-06-29T22:35:03.227

Doesn't the TI-89 work in exact mode by default if you don't have decimal points in your numbers? – dan04 – 2014-06-29T23:52:08.203

1+1 for using TI-Basic, it was my first programming language :) – Kik – 2014-06-30T17:14:18.743

Calculators are good at math. This obviously must be true. – Thane Brimhall – 2014-07-01T22:52:41.790

2@ThaneBrimhall That's the irony, a calculator failing a simple math problem – qwr – 2014-07-01T22:57:53.377

35

Java

This Fermat guy must have been sleeping. I get hundreds of solutions to the equations. I merely converted my Excel formula to a Java program.

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

The ^ operator actually means XOR in Java, as opposed to exponentiation in typical plain-text

Erwin Bolwidt

Posted 2014-06-27T23:27:22.877

Reputation: 459

Any chance on an elaboration on why this works? – Vality – 2014-06-28T18:21:09.270

20@Vality: ^ in Java is xor, not power. – marinus – 2014-06-28T18:55:00.757

3this technically works on almost any C-based languages – phuclv – 2014-06-30T11:50:06.563

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

Compiled with clang++ -O3 -o fermat fermat.cpp, tested with 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

We obviously found a, b, c > 0 so that a3 + b3 = c3 (this also works for n = 4, 5, 6, ...).

Printing a, b and c might prove a bit difficult though ...

Ventero

Posted 2014-06-27T23:27:22.877

Reputation: 9 842

Needs -lstdc++ to build on my PC. But do make sure to include the -O3 flag. It doesn't work on -O0. – dan04 – 2014-06-28T01:56:20.100

1@dan04: Oops, forgot the ++ in clang++. – Ventero – 2014-06-28T01:57:22.713

2By the way, this is not a compiler bug. C (and C++) standard allows to do anything here, as val.u can overflow (it would be different if it would be uint32_t instead). Besides, this code also uses union in incorrect way (according to standard, you cannot write to one field, and read the other field), but this is allowed by many compilers (according to their documentation). – Konrad Borowski – 2014-06-28T13:34:33.447

@xfix The same thing happens when val.u is made uint32_t or the overflow is checked. In fact, I just used the union to make the code a bit shorter (otherwise it'd require extra checks to correctly increment/reset a, b and c). I've changed the code to remove the union, and it still produces the same output. – Ventero – 2014-06-28T13:51:36.233

3The reason this is allowed is a section of the C++ standard that says:

A loop that, outside of the for-init-statement in the case of a for statement,

  • makes no calls to library I/O functions, and
  • does not access or modify volatile objects, and
  • performs no synchronization operations (1.10) or atomic operations (Clause 29)

may be assumed by the implementation to terminate. – dan04 – 2014-06-28T14:27:51.237

3

@dan04 That exact wording has actually been removed from the standard in a later draft, see US 38 in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3196.htm - but of course, it's only been generalized. This is the reason why printing out a,b,c (or anything, for that matter) in fermat() makes the function never return.

– Ventero – 2014-06-28T15:16:41.863

8

Argh I was so going to post that one. For anybody who's confused: John Regehr has a nice explanation here.

– Voo – 2014-06-28T22:59:54.817

@Voo That's not too useful without a link. John Regehr, if I even found the right blog, has 273 posts tagged computer science. – raptortech97 – 2014-08-08T19:00:42.597

@raptortech97 You missed the link that's under the word here in my comment :-) It's post 161 from the URL though if I'd to guess. – Voo – 2014-08-08T19:51:51.947

@Voo Oh yeah now I feel really stupid... – raptortech97 – 2014-08-08T20:11:39.523

13

Java

It looks like the theorem holds for n=3, but I found counterexamples for 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));
    }
}

Output:

true

Explanation:

Even if the numbers seem small, they overflow when raised to the 4th power. In reality, 644 + 4964 = 5284 - 234, but 234 becomes 0 when restricted to int (32 bits).

aditsu quit because SE is EVIL

Posted 2014-06-27T23:27:22.877

Reputation: 22 326

Can you explain this? – Anubian Noob – 2014-06-29T23:01:23.727

@AnubianNoob done – aditsu quit because SE is EVIL – 2014-06-30T06:47:09.067

9

Python

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

Who says that c must be greater than a and b?

Petr Pudlák

Posted 2014-06-27T23:27:22.877

Reputation: 4 272

2It prints True because math.pow returns floating-point numbers, and these do not have enough precision to get the correct answer, False. – kernigh – 2014-06-30T23:58:21.030

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

This approach finds a bunch of different solutions. For example:

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

How it works

The first line should start with a ~ to interpret the input. Instead of, e.g., the number 3 , variable N contains the string 3\n.
While 2 3 ? calculates 3, 2 N ? pushes the index of a character with ASCII code 2 in N (-1 for not found).
This way, 43 N ? and 82 N ? push -1 and 51 N ? pushes 0 (51 is the ASCII character code of 3).
Since -1 + 0 = -1, the condition is satisfied and (43,51,82) is a "solution".

Dennis

Posted 2014-06-27T23:27:22.877

Reputation: 196 637

4

C

Well of course you folks are all finding counterexamples, you keep on getting integer overflows. Plus, you're being really slow by iterating on c as well. This is a much better way to do it!

#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 might be great on the range, but it's still a bit lacking in precision...

fluffy

Posted 2014-06-27T23:27:22.877

Reputation: 725

4

C

We all hate integer overflows, so we'll use a small exponent n and some floating point conversions. But still the theorem would not hold for 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");
}

Output:

Disproved for 2139095040, 2139095040, 2139095040, 42: yes

Disproved for 2139095040, 2139095040, 2139095040, 90: yes

In IEEE 754, the number 2139095040, or 0x7F800000, represents positive infinity in single-precision floating point types. All pow(...) calls would return +Infinity, and +Infinity equals +Infinity. An easier task would be to disprove the Pythagorean theorem by using 0x7F800001 (Quiet NaN) which is not equal to itself according to the standard.

Yuriy Guts

Posted 2014-06-27T23:27:22.877

Reputation: 141

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 is magic, you know.

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

And also Wiles ain't one.

Javascript Number is not big enough.

Snack

Posted 2014-06-27T23:27:22.877

Reputation: 2 142

2

T-SQL

To disprove this Fermat guy's theorem, we just need to find a counter example. It seems, he was super lazy, and only tried it for really small permutation. In fact, he wasn't even trying. I found a counter example in just 0 < a,b,c < 15 and 2 < e < 15. Sorry I'm a golfer at heart so I'll ungolf this code later!

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)

Returns 1, meaning we found a counter example!

The trick is that while the first e looks like an alias, it actually is a sneaky way of changing the data type of e from an int to a floating point type equivalent to a double. By the time we got to 14 we are beyond the precision of a floating point number so we can add 1 to it and we still don't lose anything. The minification is a nice excuse to explain away my seemingly silly double declaration of a column alias in the rcte. If I didn't do this it would overflow long before we got to 14^14.

Michael B

Posted 2014-06-27T23:27:22.877

Reputation: 1 551

1

JavaScript

It appears this guy was onto something alright. Onto drugs if you ask me. Given the constraints, no set of values can be found for which the theorem holds true.

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

alert(lhs === rhs);

As in Java, the ^ operator is the bitwise XOR operator in JavaScript. The correct way to calculate the power of a number is to use Math.pow.

thomaux

Posted 2014-06-27T23:27:22.877

Reputation: 219

2For Fermat, the exponent(n) has to be >= 3. – recursive – 2014-06-30T16:05:25.990

Good point, the code still works though :) – thomaux – 2014-06-30T16:11:23.587

0

Another BASIC counterexample

10 a = 858339
20 b = 2162359
30 c = 2162380
40 IF (a^10 + b^10) = c^10 THEN
50   PRINT "Fermat disproved!"
60 ENDIF

r3mainer

Posted 2014-06-27T23:27:22.877

Reputation: 19 135