準・究極の選択

以下のようなプログラムを組んでいます。a^4+b^4+c^4+d^4=(n^4+(n+1)^4+(n+2)^4+(n+3)^4)^4=(e)^4となるような数の組み合わせを探すものです。実行はするのですが、答えがデタラメです。エラーではじくのでも実行しないのでもなく、直感的にわかるような間違った数値をかえしてきます。何が問題でしょうか。

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

unsigned long pow4(unsigned long a,int e)
{
return (a*a*a*a);
}

int main()
{
int i, j, k,z,m;
int ctr = 0;
unsigned long long int beki, sigma,temp;

FILE *file;

file = fopen("bekijyo_4.txt", "w");

for (i = 1; i < 200; i++) {
for (j = i + 1; j < 300; j++) {
for (k = j + 1; k < 400; k++) {
for (m = k + 1;m < 500;m++){
beki = pow4(i, 4) + pow4(j, 4) + pow4(k, 4) + pow4(m,4);
for(z = 1;z < 500; z++){
sigma = pow4((z-1), 4) + pow4(z, 4) + pow4((z + 1),4) + pow4((z + 2), 4);
temp = pow4(sigma, 4);
if (beki == temp) {
if (ctr == 0){
printf("ready-----go!\n");
}
ctr++;
printf("(%d ,%d ,%d,%d)=(%d ,%d ,%d, %d)=(%d) \n", i, j, k,m,(z - 1), z, (z + 1),(z + 2), sigma);
fprintf(file, "(%d ,%d ,%d ,%d)=(%d ,%d ,%d ,%d)=(%d) \n", i, j, k, m ,(z - 1), z, (z + 1),(z + 2), sigma);
}
if (beki < temp) break;
}
}
}
}
}
fclose(file);
printf("finish!");
return 0;
}

実行結果
(a,b,c,d)=(n,n+1,n+2,n+3)=(e)

(4 ,164 ,240 ,402)=(0 ,1 ,2 ,3)=(98)
(18 ,48 ,80 ,304)=(191 ,192 ,193 ,194)=(1198807058)
(24 ,264 ,336 ,414)=(28 ,29 ,30 ,31)=(3055458)
(26 ,132 ,200 ,472)=(191 ,192 ,193 ,194)=(1198807058)
(28 ,60 ,296 ,494)=(1 ,2 ,3 ,4)=(354)
(32 ,176 ,312 ,482)=(32 ,33 ,34 ,35)=(5071458)
(36 ,164 ,230 ,268)=(0 ,1 ,2 ,3)=(98)
(44 ,176 ,208 ,470)=(0 ,1 ,2 ,3)=(98)
(48 ,190 ,196 ,276)=(191 ,192 ,193 ,194)=(1198807058)
(64 ,84 ,160 ,214)=(1 ,2 ,3 ,4)=(354)
(64 ,146 ,180 ,492)=(32 ,33 ,34 ,35)=(5071458)
(72 ,108 ,244 ,258)=(26 ,27 ,28 ,29)=(2310354)
(76 ,110 ,236 ,456)=(4 ,5 ,6 ,7)=(4578)
(120 ,208 ,230 ,428)=(30 ,31 ,32 ,33)=(3968018)
(140 ,190 ,284 ,496)=(191 ,192 ,193 ,194)=(1198807058)
(152 ,226 ,352 ,424)=(4 ,5 ,6 ,7)=(4578)

よろしくお願いします。

質問者からの補足コメント

  • うれしい

    追記(1)。
    環境を書いておきます。OS win10 64ビット、使用コンパイラMingw64、エディターk2Editerです。3乗を処理していたマシンとは別のものです。(パソコンは5台あり、1台は自作(リニューアル)途中です。)小生は、現役のプログラマではありません。30年くらい前に、プログラマをしておりました。Basic やアセンブラで仕事をしており、C言語は仕事では使ったことがありません。メカトロニクスでアセンブラを使ったのが、一番のいい思い出で、C言語は、アセンブラのように、独自の開発マシンが必要ではなく、パソコンで自由に使えるので、今日までなんとなく使ってきました。
    たくさんの皆さんのご教示があり、有難く、勇気づけらりれております。
    とりあえず、Ogre7077の修正提案から始めてみたいと思います。修正案1は実行済みで、やたら時間がかかり、結果はもっと悲惨なもの。修正案2は?です

      補足日時:2021/01/24 19:51
  • つらい・・・

    追記(2)。
    Ogre7077さんさんの提案に沿って、プログラムを作り変えてみました。(a,b,c,d)を(230,240,250,255)にしてみました。結果は、(64,84,160,214)=(1,2,3,4)=(354)1個のみでした。それらしく見えますが、手計算してみると、明らかに間違っています。変数の縛りを255以下にしても、計算途中で255をオーバーしてしまう。するとまともな計算ができない。
    (printf の修飾子を%ldとか%lluにもしましたが、結果に影響はありませんでした。)
    これって、バソコンの限界ということでしょうか。
    それとも、もっと他に方法があるのでしょうか。Ogre7077さんが示されている修正案4.任意精度演算ライブラリとか導入する必要があるのかもしれません。が小生にはちょっと閾が高いです。高々これくらいの数学処理に、簡単な方法が見つからない?

      補足日時:2021/01/24 22:03
  • うーん・・・

    追記(3)。
    作り変えたプログラムです。肝心な点のみ。
    for (i = 1; i < 230; i++) {
    for (j = i + 1; j < 240; j++) {
    for (k = j + 1; k < 250; k++) {
    for (m = k + 1;m < 255;m++){
    beki = pow4(i, 4) + pow4(j, 4) + pow4(k, 4) + pow4(m,4);
    for(z = 1;z < 255; z++){
    後は同じです。Ogre7077さん、すみません。(i,j,k,m)を(a,b,c,d)にpow関数のaを他の文字に変えましたが、訳の分からないエラーになったので、そのまま使っています。
    当方、素人なので、よろしくお願いします。ネットで調べても、皆さん、いろいろ苦労されているみたいで。よろしく。

      補足日時:2021/01/25 01:49
  • どう思う?

    追記(4)。
    tacosan さん、お答えします。pow4関数は、型を long long にしました。それから、訳の分からないエラーは、再現できませんでした。したがって、(i,j,k,m,z)を(a,b,c,d,n)に変更しました。また、仰るとおり、Z(n)はこの場面では10以下で十分。
    結果はかなり悲惨なものです。やはり、何かのブレークスルーが必要だと思われます。皆さんが頼り。お礼は、最後。
    実行結果(一部)
    (1 ,2 ,3 ,4)=(1 ,2 ,3 ,4)=(354)
    (1 ,2 ,3 ,128)=(0 ,1 ,2 ,3)=(98)
    (1 ,36 ,94 ,193)=(191 ,192 ,193 ,194)=(5493774354)
    (4 ,5 ,6 ,7)=(4 ,5 ,6 ,7)=(4578)
    あるいは、Ogre7077さんの提案に沿って、変数eを上限を設けて、配列に。

      補足日時:2021/01/25 20:03
  • へこむわー

    追記(5)。
    お騒がせ。
    int i,a, b, c, d, n, temp[10]={354,978,2258,4578,8418,14354,23058,35298,51938,73938};
    for (i = 0; i < 10; i++) {
    for (a =1; a < 255; a++) {
    for (b = a + 1; b < 255; b++) {
    for (c = b + 1;c < 255; c++){
    for (d = c + 1;d < 255;d++){
    beki = pow4(a, 4) + pow4(b, 4) + pow4(c, 4) + pow4(d,4);
    if (beki == temp[i]) {
    数値はn^4+(n+1)^4+(n+2)^4+(n+3)^4;1≦n≦10。演算2秒、結果最悪。

      補足日時:2021/01/25 22:10
  • HAPPY

    追記(6)。
    本当にお騒がせしました。小生のプログラムが怪しいとは思っておりました。Ogre7077さん、tatsumaru77さん、お手数でした。やはり、ありませんか。残念です。「教えて!goo」は、この辺で終わりにします。ベストアンサーは、Ogre7077さんとtatsumaru77さんに差し上げます。とりあえず一人なので、サイコロを振って決めます。それから、Tacosanさんにも、お礼をします。皆さん、夜遅くまでお付き合いいただき、本当にありがとうございました。

      補足日時:2021/01/26 02:11

A 回答 (8件)

追記(5) について



e^4 = a^4 + b^4 + c^4 + d^4
なので、比較する temp[i] は四乗が必要

log2(73938) = 16.17...
なので、4乗すると64ビット超で桁あふれし計算不可
これ以上の計算は、任意精度演算ライブラリが必要

計算量を減らすため、計算済みの作業用変数を用意する
例)
e を決める → t0 = e^4
a を決める → t1 = t0 - a^4
...
d を決める → t4 = t3 - d^4
t4 == 0 → 見つけた!

計算量を減らすため、不要な繰り返しは行わせない
例)
b を決める → t2 を計算 → t2 < 0 ならその後の b,c,d の処理は不要
c を決める → t3 を計算 → t3 < 0 ならその後の c,d の処理は不要

余談ではありますが、
すこし計算しましたが、条件を満たす (a,b,c,d,e) の組はなさそうです...
    • good
    • 1
この回答へのお礼

有り難うございました。勉強になりました。

お礼日時:2021/01/26 02:18

範囲を500に広げましたが、1件も該当しません。


ソースは下記URLです。
https://ideone.com/qsofO3

あなたの提示された
if (beki == temp[i])は
if (beki == pow4(temp[i],4))ではないかと思いますが。。。
    • good
    • 1
この回答へのお礼

有り難うございました。お付き合いいただき、感謝しております。

お礼日時:2021/01/26 02:18

pow4 はどうなっている? あと「訳の分からないエラー」ってなに? どんな「メッセージ」が出てる?



なお, 現状では z をそんな驚異的に大きな値にするのは無駄かつ無意味. z<11 で十分.
    • good
    • 1
この回答へのお礼

有り難うございました。いつも早く連絡をいただいて、質問者としては、それだけでも、心強い気持ちになりました。

お礼日時:2021/01/26 02:18

ちょっとその「作り変えてみ」たプログラムを出してもらえませんか?



いちばん「簡単」なのは
自動的に多倍長演算するようなプログラム言語を使う
こと, なんだけどね....
    • good
    • 0

int / long は多分 32 ビット整数ですので、


上限である 2^32-1 を超えると桁あふれします。
四乗しても 2^32-1 を超えない値は、
x^4 < 2^32
x < 2^8
x < 256
であるため、256 以上の値を四乗すると破綻します。

修正案1.
関数 pow4 の引数と戻り値を 64 ビット整数の long long 型にする

修正案2.
引数 a は int のままでも、計算途中で long long になるように変形する
例) a * 1ULL * a * a * a

修正案3.
printf で long long を使用するなら、長さ修飾子 ll を指定する
例) printf("%llu", temp); // unsigned long long

修正案4.
2^64 を超える値を計算できる任意精度演算ライブラリの導入を検討する
https://ja.wikipedia.org/wiki/%E4%BB%BB%E6%84%8F …


本題とは関係ありませんが、

提案1.
変数 (i,j,k,m,z) は (a,b,c,d,n) と変えるべきです。
仕様と実装の変数名が意味もなく違うので、読んでいて混乱しました

提案2.
a^4+b^4+c^4+d^4 = e^4
を満たす (a,b,c,d,e) を探すより、
n^4+(n+1)^4+(n+2)^4+(n+3)^4 = e
を満たす (n,e) を探すほうがはるかに簡単ですので、
探索順番を以下のようにすれば計算量が削除できます。
n を決める→ 対応する e を計算 → [1,e) の範囲から a,b,c,d を探索
    • good
    • 2

unsigned long long int型は、使用できるという前提でよろしいのでしょうか?

    • good
    • 1

pow4 の方が重症だった. 用途と合致しない.



printf の書式も確認してね.
    • good
    • 1

printf の書式を確認すべし.



処理系によっては, てきとうなオプションを付ければ警告を出してくれるね.
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報