以下のようなプログラムを組んでいます。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)
よろしくお願いします。
No.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) の組はなさそうです...
No.7
- 回答日時:
範囲を500に広げましたが、1件も該当しません。
ソースは下記URLです。
https://ideone.com/qsofO3
あなたの提示された
if (beki == temp[i])は
if (beki == pow4(temp[i],4))ではないかと思いますが。。。
No.5
- 回答日時:
ちょっとその「作り変えてみ」たプログラムを出してもらえませんか?
いちばん「簡単」なのは
自動的に多倍長演算するようなプログラム言語を使う
こと, なんだけどね....
No.4
- 回答日時:
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 を探索
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語でセルオートマトンを作成...
-
16進数 加算 減算 C言語
-
VB6.0での小数点の扱いについて
-
CRCの計算方法について
-
BCD・HEX・BINについて
-
c languageで 簡単な質問があ...
-
ExcelでPC(パソコン)によって...
-
O(n log n)について2
-
EXCELの関数"STDEV(標準偏差)"...
-
VisualBasic と Fortran の計算...
-
VBAのINT関数について
-
2進数 → 10進数変換 模範解答と...
-
ExcelのINT関数の計算結果がお...
-
10進数での「25」が2進数では「...
-
0~2πの範囲を十等分して…
-
VB.net Double と...
-
VBAでミリ秒まで出力する方法
-
Log関数に関する質問
-
floatの有効桁数
-
大きすぎる数値になるとE+にな...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
O(n log n)について2
-
VB.net Double と...
-
c languageで 簡単な質問があ...
-
ExcelのINT関数の計算結果がお...
-
有効数字について 以前質問をし...
-
ExcelでPC(パソコン)によって...
-
三菱シーケンサ(Aシリーズ)で...
-
除算を使わずに10で割りたい。
-
16進数 加算 減算 C言語
-
EXCELの関数"STDEV(標準偏差)"...
-
VB6.0での小数点の扱いについて
-
”/”を使わずに割り算したいんで...
-
距離から緯度経度を求める方法
-
VBAでミリ秒まで出力する方法
-
floatの有効桁数
-
コンピューターは指数関数をど...
-
時刻の比較
-
計算の丸め誤差の解消について
-
Double型について
-
powf を使わずにべき乗を計算
おすすめ情報
追記(1)。
環境を書いておきます。OS win10 64ビット、使用コンパイラMingw64、エディターk2Editerです。3乗を処理していたマシンとは別のものです。(パソコンは5台あり、1台は自作(リニューアル)途中です。)小生は、現役のプログラマではありません。30年くらい前に、プログラマをしておりました。Basic やアセンブラで仕事をしており、C言語は仕事では使ったことがありません。メカトロニクスでアセンブラを使ったのが、一番のいい思い出で、C言語は、アセンブラのように、独自の開発マシンが必要ではなく、パソコンで自由に使えるので、今日までなんとなく使ってきました。
たくさんの皆さんのご教示があり、有難く、勇気づけらりれております。
とりあえず、Ogre7077の修正提案から始めてみたいと思います。修正案1は実行済みで、やたら時間がかかり、結果はもっと悲惨なもの。修正案2は?です
追記(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.任意精度演算ライブラリとか導入する必要があるのかもしれません。が小生にはちょっと閾が高いです。高々これくらいの数学処理に、簡単な方法が見つからない?
追記(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を他の文字に変えましたが、訳の分からないエラーになったので、そのまま使っています。
当方、素人なので、よろしくお願いします。ネットで調べても、皆さん、いろいろ苦労されているみたいで。よろしく。
追記(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を上限を設けて、配列に。
追記(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秒、結果最悪。
追記(6)。
本当にお騒がせしました。小生のプログラムが怪しいとは思っておりました。Ogre7077さん、tatsumaru77さん、お手数でした。やはり、ありませんか。残念です。「教えて!goo」は、この辺で終わりにします。ベストアンサーは、Ogre7077さんとtatsumaru77さんに差し上げます。とりあえず一人なので、サイコロを振って決めます。それから、Tacosanさんにも、お礼をします。皆さん、夜遅くまでお付き合いいただき、本当にありがとうございました。