質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

4回答

1250閲覧

c言語で

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2016/11/25 17:58

編集2016/11/27 11:27

c言語初心者です、下記の条件を満たすプログラムの書き方がよくわからないのですがどのようにしたらいいのでしょうか?

1・倍精度浮動小数点数のn×n正方行列2つの積を計算するプログラム
2・計算時間は1秒以内
3・nをどこまで大きくできるかチャレンジ

n×n正方行列2つの積を計算するプログラム,計算時間は1秒以内
という条件は満たしているのですが、nをどこまで大きくできるかがうまくできません。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

退会済のようですが・・・今時の環境で1秒に計算できる正方行列のサイズは10万を超えると思います(以下のプログラムで1000までは試しましたが時間が短すぎて計測できませんでした)。10万だとdoubleが8バイトとして約240GBのメモリが必要です。環境依存と言えばそうなのですが・・・いまいち出題者の意図が分かりません。
(FreeBSD 10.3-RELEASE-p11 clang version 3.8.1)

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <time.h> 4 5#define MAXSIZ (10000) 6 7void init(double m[MAXSIZ][MAXSIZ], int siz); 8void mClear(double m[MAXSIZ][MAXSIZ], int siz); 9void multiply(const double mA[MAXSIZ][MAXSIZ],const double mB[MAXSIZ][MAXSIZ],double mC[MAXSIZ][MAXSIZ],int siz); 10void print(const double m[MAXSIZ][MAXSIZ], int siz); 11// 12double mA[MAXSIZ][MAXSIZ]; 13double mB[MAXSIZ][MAXSIZ]; 14double mC[MAXSIZ][MAXSIZ]; 15// 16int main(int agc, char *agv[]) 17{ 18 if( agc != 2 ){ 19 fputs("Error agc!=2\n",stderr); 20 exit(1); 21 } 22 // 23 int matSiz= atoi(agv[1]); 24 // 25 if( matSiz < 1 || MAXSIZ < matSiz){ 26 fputs("Error matSiz\n",stderr); 27 exit(2); 28 } 29 // 30 init(mA,matSiz); 31 init(mB,matSiz); 32 mClear(mC,matSiz); 33 // 34 clock_t st= clock(); 35 multiply(mA, mB, mC, matSiz); 36 clock_t et= clock(); 37 // 38 print(mC,matSiz); 39 printf("MatSiz= %d %f msec\n",matSiz, ((et-st)*1000.0)/CLOCKS_PER_SEC); 40 // 41 return 0; 42} 43// 44void init(double m[MAXSIZ][MAXSIZ], int siz) 45{ 46 for( int i= 0; i < siz; i++){ 47 for( int j= 0; j < siz; j++){ 48 m[i][j]= (double)rand()/(double)RAND_MAX; 49 } 50 } 51} 52// 53void mClear(double m[MAXSIZ][MAXSIZ], int siz) 54{ 55 for( int i= 0; i < siz; i++){ 56 for( int j= 0; j < siz; j++){ 57 m[i][j]= 0.0; 58 } 59 } 60} 61// 62void multiply(const double mA[MAXSIZ][MAXSIZ],const double mB[MAXSIZ][MAXSIZ],double mC[MAXSIZ][MAXSIZ],int siz) 63{ 64 for( int i= 0; i < siz; i++){ 65 for( int j= 0; j < siz; j++){ 66 for( int k= 0; k < siz; k++){ 67 mC[i][j] += mA[i][k]*mB[k][j]; 68 } 69 } 70 } 71} 72// 73void print(const double m[MAXSIZ][MAXSIZ], int siz) 74{ 75 for( int i= 0; i < siz; i++){ 76 for( int j= 0; j < siz; j++){ 77 printf("%2.4f ",m[i][j]); 78 } 79 putc('\n',stdout); 80 } 81} 82 83

投稿2016/12/02 09:42

編集2016/12/02 22:16
cateye

総合スコア6851

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

raccy

2016/12/02 10:12

mC[i][j]= mA[i][k]*mB[k][j]; は mC[i][j]+= mA[i][k]*mB[k][j]; だと思います(その前にも0.0で初期化が要りますが)。Clangの最適化は恐ろしいほど優秀なので、for( int k= 0; k < siz; k++){...}の部分は最適化で最後のmC[i][j]= mA[i][siz-1]*mB[siz-1][j];しか計算されていないのでは無いかと思われます。 なお、手元(macOS)で同じような実装をした物で試したところ、GCC 6.2.0だと564個までしかできませんでした。でも、Clangだと6001個ぐらいと10倍以上も違う…。私のはVLAでスタックに積んだ実装なのでで、mallocでヒープに割り当てた場合も最適化のされ方が何か違ってきそうな気がします。
cateye

2016/12/02 22:23

ご指摘ありがとうございます。ソース修正して差し替えました。10万というのは私の思い違いでですね^^;・・・結果は以下の通り・・・私の環境では700~800のあたりにありそうです。 MatSiz= 500 382.812500 msec MatSiz= 600 750.000000 msec MatSiz= 700 898.437500 msec MatSiz= 800 1359.375000 msec  CPU:AMD A10-6800K 4.1~4.4G
guest

0

こんにちは。

推測ですが、nを#defineすることはできても、int n;にできなくて困っているのですよね?
であれば、malloc()で獲得すると良いです。1次元配列になりますが、2次元的にアクセスすることは可能です。

C

1double* array=(double*)malloc(sizeof(array)*n*n); // nxn個の領域を確保する 2 3// とりあえず初期化 4for (int i=0; i < n; ++i) 5 for (int j=0; j < n; ++j) 6 array[j*n+i]=0; // array[i][j]と同等なアクセス 7 8// 必要な処理はここへ 9 10free(array); // 開放を忘れずに

arrayは1次元なのでarray[i][j]とは書けません。
でも、array[j*n+i]ならば、n x n正方配列の(i, j)要素へアクセスしているのと同等です。

投稿2016/11/26 01:02

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

「n×n正方行列2つの積を計算するプログラム,計算時間は1秒以内」ができているというのであれば、まず、その部分を下記のような関数にします。@detailの内容は適当なので実際の実装にあわせてください。

C

1#include <stdbool.h> 2/** 3 * n x n 正方行列2つの積を計算し、計算時間が1秒以内かを判断する。 4 * @brief 要約説明 5 * @param (int n) 行列のサイズ。n x n 正方行列で計算される。 6 * @return 1秒以内なら true、でなければ false を返す。 7 * @detail 行列の各要素は double (通常はIEEE 754 倍精度浮動小数点数)である。 8 * 行列の各要素は[0, 1)の乱数(randを使用)を用いる。乱数の生成時間は計算時間に含まれない。 9 * 計算時間は clock() を用いてプログラムが使用した時間である。実際に経過した時間ではない。 10 * メモリを確保できない場合は false を返し、errno に ENOMEM をセットする。 11 */ 12bool matrix_product_onesec(int n) 13{ 14 // 実装を書く 15}

あとは、nを増やしながら、上の関数で確認していくだけです。どこまで確認するかは指定できるようにするといいでしょう。

C

1int max_calcable(int m) 2{ 3 for (int i = 1; i <= m; i++) { 4 if (!matrix_product_onesec(i)) return i - 1; 5 } 6 return m; 7}

false が返ってきたとき、それまで成功していた数、つまり、i - 1を返すことがコツになります。最大まで達していれば、最大を返します。

投稿2016/11/25 21:14

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

課題の意図はこういうことではないでしょうか。(計測処理は端折りました)

double n = 0; while(1秒内) { pow(n,2.0); // math.h n++; } printf("n=%f",n);

投稿2016/11/25 19:26

fromageblanc

総合スコア2724

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問