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

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

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

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

Q&A

解決済

4回答

1805閲覧

プログラムの改善

mikann_

総合スコア21

C

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

0グッド

0クリップ

投稿2016/07/20 15:30

編集2016/07/21 04:57

###前提・実現したいこと
C言語で数値計算のプログラムを書きました。
効率が悪いところや、他の書き方がありましたら、アドバイスしていただけると助かります。

###該当のソースコード

C言語

1#include <stdio.h> 2#include <math.h> 3 4double rh=1.; 5double w; 6int main(){ 7 8while (rh <= 3){ 9if (0<=rh && rh<=1){ 10w = 1.-3.*pow(rh,2)/2.+3.*pow(rh,3)/4.; 11} 12else if(1<=rh && rh<=2){ 13w = pow((2-rh),3)/4.; 14} 15else{ 16w=0; 17} 18printf("%f %f\n",rh,w); 19rh += 0.1; 20} 21return 0; 22} 23 24###発生している問題・エラーメッセージ 25 26問題はありませんが、上記のプログラム以外でも良い書き方があれば教えていただきたいです。

###試したこと
現在勉強中で他の書き方も試していますが、何か良い方法があればアドバイスいただきたいです。

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

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

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

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

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

swordone

2016/07/20 15:54

そもそも何をしようとしているかもわからないのに、アドバイスも何も無いと思いますが。
fuzzball

2016/07/21 00:14

関係のないタグを付けないで下さい。
ttyp03

2016/07/21 00:26

C言語以外のタグをつけているのにはどういった意図があるのですか?
takito

2016/07/21 02:23

他サイトで同じ質問が。どうやらタグの言語でそれぞれにコードを見てみたいようですね?どのような学習のためかわかりませんが、Java,C++,FORTRANでのご自身のコードも載て具体的な理由や意図を書かれた方が、適切な回答やアドバイスを得られると思いますよ。
swordone

2016/07/21 03:05

編集前の質問を見ると、JavaとかFORTRANでのコードを教えてくれって言うないようになってるんですよね。だからタグがその辺りのものがついたままになっている。 この質問に切り替えた以上、関係ないタグは外すべきです。
mikann_

2016/07/21 04:59

申し訳ありません。不適切なタグを付けていました。訂正いたしました。ご意見ありがとうございます。
guest

回答4

0

ベストアンサー

  • インデントされていない。
  • rhwがグローバル変数である必要性がない。変数のスコープは最小限にすべき。
  • ある値からある値までを数ステップずつ刻むならfor文の方がわかりやすい。
  • たかが二乗、三乗にpow()は不要。普通に掛けた方が速くなる。
  • 計算部分は関数に分けるべき。インライン関数にすれば速度も落ちない。
  • 1.でdoubleで表現すると1と見分けが付きにくい。1.0とすべき。
  • そもそも自動昇格されるのだから、浮動小数点数のリテラルにする意味はない。
  • 条件分岐が冗長。0≦rh≦1, 1≦rh≦2, 他 よりも、rh<0, rh≦1, rh≦2, 他 の方が比較回数が1回減る。
  • 3. * pow(rh, 2) / 2.とするより 1.5 * pow(rh, 2)なのでは。最適化で同じにはなりそうだけど。
  • C言語ではint main(void)int main(int argc, char* argv[])である。C言語では(void)()は意味が異なる。
  • C言語とありながら、タグにはJava、C++、FORTRANとあるが、他の言語でも良いと言うことか?

C

1#include <stdio.h> 2 3static inline double calc(double x) 4{ 5 if (x < 0) { 6 return 0; 7 } else if (x <= 1) { 8 return 1 - 1.5 * x * x + 0.75 * x * x * x; 9 } else if (x <= 2) { 10 double y = 2 - x; 11 return y * y * y / 4; 12 } else { 13 return 0; 14 } 15} 16 17int main(void) 18{ 19 for (double rh = 1; rh <= 3; rh += 0.1) 20 printf("%f %f\n", rh, calc(rh)); 21 return 0; 22}

投稿2016/07/20 20:08

raccy

総合スコア21735

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

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

yuba

2016/07/21 03:27

0.1刻みを表現するところは、katoyさんのやっておられるように直前で10で割るやり方が精度上の問題を排除できて良いかと思います。
guest

0

c

1#include <stdio.h> 2#include <math.h> 3 4double func(double rh) { 5 double ans = 0; 6 if (0.0 <= rh && rh <= 1.0) { 7 ans = 1.0 - 3.0 * pow(rh, 2) / 2.0 + 3.0 * pow(rh, 3) / 4.0; 8 } 9 else if (1.0 < rh && rh <= 2.0) { 10 ans = pow((2.0 - rh), 3) / 4.0; 11 } else { 12 ans = 0; 13 } 14 return ans; 15} 16 17int main(void) { 18 // [1.0 ... 3.0] の間の値を 0.1 刻みで変化させていく 19 for (int i = 10; i <= 30; i++) { 20 double rh = i / 10.0; 21 printf("%f %f\n", rh, func(rh)); 22 } 23 return 0; 24}

主な変更点:
* 値の計算部分を関数として独立させた。
* rh を 0.1 刻みで変化させるループを while から for に変更した。
* rh += 0.1 は計算誤差が累積していく可能性があるので、
ループ制御変数を整数にして、その整数から rh を求めるようにした。
* double の数値は 1. でなく 1.0 のように記述するようにした。
* 適宜 SPACE を挿入して読みやすくした。

投稿2016/07/20 22:36

katoy

総合スコア22324

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

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

katoy

2016/07/21 15:33

参考として、double での足し算をたくさん繰り返すと計算誤差が累積されてくる例を示します。 ```c #include <stdio.h> int main(void) { double r = 10.0; for (int i = 0; i < 100000; i++) { r += 0.000001; } printf("%.16f\n", r); return 0; } ``` 実行例: ``` $ gcc x.c $ ./a.out 10.0999999999251600 ``` 11.0 ピッタリにはなりません。
guest

0

インデントもなければコメントもない。
なにやってんのか/なにをもとめているのかわからん。
ウチの新人がこんなコード書いてきたら窓から投げ捨てる。

投稿2016/07/20 20:29

episteme

総合スコア16614

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

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

0

c

1#include <stdio.h> 2 3static inline double w(double rh) { 4 return (rh<=0) ? 0 : 5 (rh<=1) ? 1.0 - (3.0 * rh * rh / 2.0) + (3.0 * rh * rh * rh / 4.0) : 6 (rh<=2) ? (2.0-rh) * (2.0-rh) * (2.0-rh) / 4.0 : 7 0; 8} 9 10int main(void) { 11 for(double rh=1.0; rh<=3.0; rh+=0.1) { 12 printf("%f %f\n",rh,w(rh)); 13 } 14 return 0; 15}

主な変更点:

  • 値の計算部分を関数wとして独立させて可読性を上げた。
  • ループを while から for に変更し、ループに関する仕様をfor文に集めて可読性を上げた。
  • double の数値は 1. でなく 1.0 のように記述するようにして可読性を上げた。
  • 適宜 SPACE を挿入して可読性を上げた。
  • 三項演算子を使って可読性を上げた。三項演算子かわいい。
  • pow を開いた。math.h を捨てた。

投稿2016/07/21 01:12

matobaa

総合スコア2493

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問