- PR -

Fermatの最終定理

1
投稿者投稿内容
しんにぃ
会議室デビュー日: 2006/09/05
投稿数: 17
投稿日時: 2008-01-07 15:37
現在、Fermatの最終定理をプログラムを組んで証明しようとしています。もちろん自然数は無限大にあるわけですから限界があることはわかっていますのでできるところまでという目標のもとやっています。
現在、下のようなプログラムをJavaを用いて組んで走らせてみているのですが、nが16の段階で式が成り立ってしまうという現象が起きてしまっています。たぶんなのですが、double型を用いてるために10^16という数値が限界を超えてしまって計算結果がおかしくなってしまっているのだと思うのですが、いまいち解決の仕方がわかりません。どなたかご助言をお願いします。


/*Javaプログラム*/

import java.lang.Math;
public class Jikkou {

public static void main(String[] args){
double n,x,y,z;
System.out.println("n x y z");
for(n=2;n<=20;n++){
for(x=1;x<=10;x++){
for(y=1;y<=x;y++){
for(z=1;z<=(x+y);z++){
if(Math.pow(x,n)+Math.pow(y,n)==Math.pow(z,n)){
System.out.println(Math.pow(x,n)+"+"+Math.pow(y,n)+"=="+Math.pow(z,n));
System.out.println(n+" "+x+" "+y+" "+z);
}
}
}
}
}
}
}


/*実行結果*/

n x y z
16.0+9.0==25.0
2.0 4.0 3.0 5.0
64.0+36.0==100.0
2.0 8.0 6.0 10.0
1.0E16+1.0==1.0E16
16.0 10.0 1.0 10.0
1.6677181699666568E16+1.0==1.6677181699666568E16
17.0 9.0 1.0 9.0
1.0E17+1.0==1.0E17
17.0 10.0 1.0 10.0
1.8014398509481984E16+1.0==1.8014398509481984E16
18.0 8.0 1.0 8.0
1.50094635296999136E17+1.0==1.50094635296999136E17
18.0 9.0 1.0 9.0
1.0E18+1.0==1.0E18
18.0 10.0 1.0 10.0
1.1398895185373144E16+1.0==1.1398895185373144E16
19.0 7.0 1.0 7.0
1.44115188075855872E17+1.0==1.44115188075855872E17
19.0 8.0 1.0 8.0
1.350851717672992E18+1.0==1.350851717672992E18
19.0 9.0 1.0 9.0
1.0E19+1.0==1.0E19
19.0 10.0 1.0 10.0
7.9792266297612E16+1.0==7.9792266297612E16
20.0 7.0 1.0 7.0
1.15292150460684698E18+1.0==1.15292150460684698E18
20.0 8.0 1.0 8.0
1.2157665459056929E19+1.0==1.2157665459056929E19
20.0 9.0 1.0 9.0
1.0E20+1.0==1.0E20
20.0 10.0 1.0 10.0
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2008-01-07 15:52
たぶん、誤差でしょう。
doubleは1bitの負号、11bitの指数部、52bitの仮数部を持ちます。

52bit = 10bit ^ 5 + 2bit ≒ 10 ^ 3 ^ 5 * 4 = 4 * 10 ^ 15
程度までは仮数部の精度から整数は誤差なく表現できることが期待できますが
それ以上の数値については誤差で整数を隙間なく表現することができないでしょう。

整数でそれなりの大きさまで扱えればいいというのであれば
longを用いることで63bitの大きさで整数を扱えますし、
それ以上の精度が必要であればjava.math.BigDecimalを用いましょう。
blunder
ベテラン
会議室デビュー日: 2003/09/11
投稿数: 65
投稿日時: 2008-01-07 16:39
java.math.BigInteger(任意精度の整数)を使えばよいです。
yuzy
大ベテラン
会議室デビュー日: 2002/02/14
投稿数: 117
投稿日時: 2008-01-07 17:11
引用:

現在、Fermatの最終定理をプログラムを組んで証明しようとしています。



質問者の方は、おわかりになっていると思いますが、
プログラムで<<証明>>はできません。

「フェルマーの最終定理」サイモン・シン著
は、かなりおもしろかったです。
もし、読んでいなければ一読をお勧めいたします。

(この本の中でも、コンピュータを使って<<証明>>することはできない。
 と書かれています。
 定理に反する解を見つけられたら、その定理が成立しないことは証明できますが、
 定理に反する解を見つけられないからといって、その定理が成立するとは言えません。
 その例についても、本の中で触れられています。)
しんにぃ
会議室デビュー日: 2006/09/05
投稿数: 17
投稿日時: 2008-01-07 18:20
nagiseさん
詳しい解説ありがとうございます。やはりdouble型では限界があるのですね。
java.math.BigDecimalというのは初めて知りました。調べてみたいと思います。

>blunderさん
さっそく調べさせてもらいました。多倍長整数というものがあるのですね。こんな便利なものがあるとは、勉強になりました。ありがとうございます。

>yuzyさん
わかってはいるのですが、証明というものが昔から苦手でしてww
擬似的にでもプログラムでできればと思いやってみた次第ですw
お勧めいただいた本は早速図書館に行って探してみたいと思います。
ありがとうございました。
しんにぃ
会議室デビュー日: 2006/09/05
投稿数: 17
投稿日時: 2008-01-07 18:27
みなさんのご助言のもと改良したプログラムによって、何とか正常に動かすことが可能となりましたので、計算結果とともにのせておきます。へたれなプログラムですがご容赦くださいw


/*改良したプログラム*/
import java.math.*;
public class Jikkou {

public static void main(String[] args){
int n; //冪乗の値
int x,y,z;//X^n+Y^n=Z^nの式内の変数にそれぞれ対応
int count=0;//試行回数のカウント用

for(n=2;n<=100;n++){//何乗まで計算するか
for(x=1;x<=100;x++){//xの値の範囲の決定(1〜?)
for(y=1;y<=x;y++){//yの値の範囲の決定(1〜x)
for(z=x;z<=(x+y);z++){//zの値の範囲の決定(x〜x+y)

/*現在のx,y,zを用いて多倍長整数X,Y,Zを生成*/
BigInteger X = new BigInteger(Integer.toString(x));
BigInteger Y = new BigInteger(Integer.toString(y));
BigInteger Z = new BigInteger(Integer.toString(z));

/*X^n+Y^n=Z^nの式が成り立つかの判定*/
if(X.pow(n).add(Y.pow(n)).equals(Z.pow(n))){//pow(n)はBigIntegerクラスが持つn乗を計算するクラスメソッド
/*デバッグと途中経過表示用*/
System.out.println(X.pow(n)+"+"+Y.pow(n)+"=="+Z.pow(n));
System.out.println("n="+n+" "+"x="+x+" "+"y="+y+" "+"z="+z);
}
/*試行回数をインクリメント*/
count++;
}
}
}
}
/*結果表示用*/
System.out.println("試行回数");
System.out.println(count);
}
}


/*計算結果*/
16+9==25
n=2 x=4 y=3 z=5
64+36==100
n=2 x=8 y=6 z=10
144+25==169
n=2 x=12 y=5 z=13
144+81==225
n=2 x=12 y=9 z=15
225+64==289
n=2 x=15 y=8 z=17
256+144==400
n=2 x=16 y=12 z=20
400+225==625
n=2 x=20 y=15 z=25
441+400==841
n=2 x=21 y=20 z=29
576+49==625
n=2 x=24 y=7 z=25
576+100==676
n=2 x=24 y=10 z=26
576+324==900
n=2 x=24 y=18 z=30
784+441==1225
n=2 x=28 y=21 z=35
900+256==1156
n=2 x=30 y=16 z=34
1024+576==1600
n=2 x=32 y=24 z=40
1225+144==1369
n=2 x=35 y=12 z=37
1296+225==1521
n=2 x=36 y=15 z=39
1296+729==2025
n=2 x=36 y=27 z=45
1600+81==1681
n=2 x=40 y=9 z=41
1600+900==2500
n=2 x=40 y=30 z=50
1764+1600==3364
n=2 x=42 y=40 z=58
1936+1089==3025
n=2 x=44 y=33 z=55
2025+576==2601
n=2 x=45 y=24 z=51
2025+784==2809
n=2 x=45 y=28 z=53
2304+196==2500
n=2 x=48 y=14 z=50
2304+400==2704
n=2 x=48 y=20 z=52
2304+1296==3600
n=2 x=48 y=36 z=60
試行回数
2314125
Gio
ぬし
会議室デビュー日: 2003/11/28
投稿数: 350
お住まい・勤務地: 都内から横浜の間に少量発生中
投稿日時: 2008-01-08 00:05
興味でやっていることに水を差すつもりはありませんが、少しだけ補足します。

(1) 「フェルマーの最終定理」という呼称は正しくありません。
「フェルマー予想」あるいは「ワイルズの定理」です。

(2) n=2 の場合、x^2+y^2=z^2 を満たす整数解は以下の式で尽くされます。(これ以外に解はなく、すべての解はこの形で表現できる)

任意の整数 m, n に対して
x=m^2-n^2
y=2*m*n
z=m^2+n^2
1

スキルアップ/キャリアアップ(JOB@IT)