🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

Q&A

解決済

2回答

1372閲覧

コンパイラの実装のされ方やメモリの使用状況によって誤った結果を防ぐ方法

zera

総合スコア5

C

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

GCC

GCCはGNU Compiler Collectionの略です。LinuxのC言語コンパイラのデファクトスタンダードであり、数多くの他言語やプラットフォームサポートもします。

コンパイラ

コンパイラは、プログラミング言語で記述したソースコードを、コンピュータの実行形式であるオブジェクトコードに変換するプログラムです。

0グッド

2クリップ

投稿2021/01/22 16:04

c言語について質問です。
1/1+x**2の0から1までの積分がπ/4になることを利用して円周率πの値を出すプログラムを作りました。モンテカルロ法のように一辺1の正方形に点を乱数によって打ち込みそれの比によって面積計算をしています。また、コマンドライン引数で打ち込む回数とπを計算する回数を指定するようにしています。その後πの平均値と分散を算出しています。

以下のプログラムでコンパイラの実装のされ方やメモリの使用状況によって誤った結果が得られる場合があると言われたのですがどこの部分がおかしいのでしょうか?

コンパイル環境
OS: ubuntu 20.04
コンパイラ: gcc

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <time.h> 4#include <math.h> 5 6 7int main(int argc, char *argv[]){ 8 9 int iterate, i; /* number of iteration */ 10 int pi_num, j; /* number of PI */ 11 int all; /* sample of the all points */ 12 int und_func; /* number over the function */ 13 double x; /* cordinate of x */ 14 double y; /* cordinate of y */ 15 double pi; /* value of pi */ 16 double sum; /* sum of pi */ 17 double average; /* pi average */ 18 double deviation;/* square of deviation */ 19 double stan_devi;/* value of standard deviation */ 20 21 if( argc != 3){ 22 fprintf(stderr, "Please input command-line arguments\n"); 23 fprintf(stderr, "EX; file, number of sample, number of PI's execution\n"); 24 return(1); 25 } 26 sscanf(argv[1], "%d", &iterate); 27 sscanf(argv[2], "%d", &pi_num); 28 double pi_arr[pi_num]; 29 30 srand(time(NULL)); 31 32 33 for(j=0; j<pi_num; j++){ 34 all = 0; 35 und_func = 0; 36 for(i=0; i<iterate; i++){ 37 x = (double)rand()/RAND_MAX; /* generation of x cordinate */ 38 y = (double)rand()/RAND_MAX; /* generation of y cordinate */ 39 40 if ( y <= 1.0/(1.0+x*x) ){ 41 all++; 42 und_func++; 43 } else { 44 all++; 45 } 46 47 } 48 pi = 4.0 * ((double)und_func / (double)all); 49 pi_arr[j] = pi; 50 printf("No %d: PI = %.8lf\n", j+1, pi); 51 52 } 53 54 printf("\n\n"); 55 56 /* calculation of average */ 57 for(j=0; j<pi_num; j++){ 58 sum += pi_arr[j]; 59 } 60 average = sum / (double)pi_num; 61 62 /* calculation of standard deviation */ 63 for(j=0; j<pi_num; j++){ 64 deviation += (pi_arr[j]-average)*(pi_arr[j]-average); 65 } 66 stan_devi = sqrt( (1/(double)pi_num) * deviation); 67 68 printf("PI average: %.8lf\n", average); 69 printf("PI standard_deviation: %.8lf\n\n", stan_devi); 70 71 return(0); 72 } 73 74 75

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

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

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

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

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

ppaul

2021/01/22 22:50

コンパイラの実装は関係ありません。 単独で実行した場合は、OSがメモリの初期化を行うかどうかによります。 他のプログラムからロードされて実行された場合には、たいてい誤った結果になります。
guest

回答2

0

ベストアンサー

sumdeviation が初期化されていないことの他には、配列の大きさが定数式ではないという点がありますね。

古い C では配列の大きさは定数式で与えなければなりませんでしたが、 C99 (C の仕様の 1999 年の改定) で定数式でなくてもよいとする規則 (variable-length array) が追加されて、 C11 (C の仕様の 2011 年の改定) では VLA は仕様には含まれるもののオプショナルな仕様 (実装しない処理系を認める) になりました。 若干流動的な仕様です。

gcc を前提にするなら gcc は C99 を完全にサポートしていることを保証しています。

また、 VLA は配列をスタックから確保する実装になっているのが普通ですが、スタックの大きさの上限は小さめに設定されているのが通例です。 Ubuntu のデフォルトだとたぶん 8MB 程度が上限です。 今回の質問者が示した例ではユーザの入力した値に従って配列を確保しているので大きな値を入力した場合にはスタックが溢れて破綻するかもしれません。 (Ubuntu だと誤った結果になるというよりもエラーとして検出されるはずですが。)

大きさの上限が事前に見積もれるか制限できる場合でない限り VLA は使わないで済むなら使わないに越したことは無いです。


それから rand については C の仕様では具体的な性質がほとんど決められていません。 具体的なアルゴリズムは各処理系の裁量で決めて良いことになっていて、乱数としての質がどのくらいのものなのかわかりません。

伝統的に線形合同法が用いられることが多く、線形合同法は多次元にマッピングしたときにはっきりした格子状に配置されることがわかっているのでシミュレーションに使うには向いていないです。

投稿2021/01/23 00:01

SaitoAtsushi

総合スコア5684

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

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

zera

2021/01/23 06:29

ありがとうございました。コンパイラについての自分の知識が未熟だと感じました。 コンパイラについてもっと勉強してみようと思います。
guest

0

これは teratail 住民への挑戦状ですね!
deviation と sum が 初期化されていないとかですか?

投稿2021/01/22 18:20

68user

総合スコア2022

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問