みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

c言語で、繰り返し文の中で、0.01づつ増やすには?

c言語で、繰り返し文の中で、0.01づつ増やすには?

c言語で、繰り返し文の中で、0.01づつ増やすにはどうすればよいのでしょうか?

関数F(x)=x3+2x-1
の値でx=0から5まで0.01刻みで増やし、出力させる
プログラムを作成せよ。という問題です。

#include <stdio.h>
int main()
{
double i;
for(i=0;i<=5;i+=0.01){
printf("%lf",i*i*i+2*i-1);
putchar('\n');
}

return(0);
}

で、はじめにi=0なので、はじめは-1のはずですが、なぜか初めの値が11.28…と表示されます。これを0.1刻みで i+=0.1 とすると正常に作動するのですがどうでしょうか?

お願いします。

投稿日時 - 2010-11-08 23:45:21

QNo.6306677

困ってます

質問者が選んだベストアンサー

ちなみに、

double i; で、 i = 0; と書いたとき、0 は確かに int ですが、double である i への代入で正常に「暗黙の型変換」が発生しますから、i = 0.0 とわざわざ書かなくても正常に代入されます。

あと、printf() における double に対する書式指指定子は、%lf ではなくて、%f です。(scanf() は、float は、%f, double は、%lf です)
printf() のような、可変数引数の関数では、float は暗黙のうちに double に変換された後に渡されるので、printf() の場合、float も double もどちらも "%f" が正しい指定です。(ただし、C99 の規格では書いても許容されることになったらしい)

0.01 ずつ誤差無し(実際には誤差最小)で加算するのは、No.2 で回答されていますが、


#include <stdio.h>
int main()
{
int i;
for(i=0;i<=500;i++)
{
double x = i / 100.0; // こっちの 100.0 は、100 だと良くないことが起こります。100 だと int / int になるから。

printf("%f",x*x*x+2*x-1);
putchar('\n');
}

としてみたり、また、double であっても、数値として小数点以下がない場合は加算による誤差は発生しないので、
#include <stdio.h>
int main()
{
double i;
for(i=0;i<=500;i++)
{
double x = i / 100;

printf("%f",x*x*x+2*x-1);
putchar('\n');
}
でも同じです。

投稿日時 - 2010-11-09 10:36:49

このQ&Aは役に立ちましたか?

8人が「このQ&Aが役に立った」と投票しています

回答(10)

ANo.10

さて、forとwhileの等価性に関する話題が一段落したところで、本題への回答です。

>はじめは-1のはずですが、なぜか初めの値が11.28…と表示されます。

コマンドプロンプトか何かで実行していますか?
0.01きざみだと500行くらい出力しますよね。
結果をすべて表示するには画面バッファーの大きさが足りないのかも。
コマンドプロンプトのプロパティで、「画面バッファのサイズ」の「高さ」を増やしてみてください。

>0.1刻みで i+=0.1 とすると正常に作動する

これは、出力行数が画面バッファーのサイズ内に収まっているからでありましょう。

投稿日時 - 2010-11-10 00:09:07

ANo.9

>・for文とwhile文は等価じゃないですよ~

そうではなくて、等価な場合とそうでない場合がある、というのが正しいです。
私自身、何が何でも等価だと主張する気はさらさらありません。

A;
while (B) {
/* 何かの文 */
C;
}

と、

for (A; B; C) {
/* 何かの文 */
}

とは、「何かの文」に
continue;
を含まなければ等価だ、ということです。理解できますか?

投稿日時 - 2010-11-09 21:30:43

ANo.8

#6 では「今回の場合」と限定しているので, 「一般論として while と for が全く等価」という意味を持たせているわけじゃないと思いますよ>#7.

個人的には「for の代わりに while を使うこと」が的外れであるという #6 の見解に賛成. というか, 制御文の意味を考えれば, 本件に関してはむしろ「当然 for を使うべし」と判断します. 「for文のindexに小数点を利用するのは一般的でない」という点には賛成するものの (cf. #2), それは「整数を使え」と誘導すべきであり, 「じゃあ while」というのは筋がずれてる.

C の場合 while は実は for のサブセットでしかないので, 理論上「for があれば while は不要」ということはできます. でも, while がないと
for (;expression;) statement
とせざるを得ず, 「expression が泣いてるように見える」ので嫌 :-)

投稿日時 - 2010-11-09 18:18:04

ANo.7

> No.6さん

ご指摘ありがとうございます、甘んじて受けましょう(^^
それに反論する気はありませんが、質問者様が誤解しない
ようにフォローだけはさせて下さい。

・for文とwhile文は等価じゃないですよ~、今回の例では
結果が同じですが、動きとしては異なりますし、可読性も
変化します。forとwhileが等価であれば、そもそもwhile文は
Cに不要=実装されないはずですから……。

・「for文のindexに小数点を利用するのは一般的でない」と
明示した点を汲んでもらえると助かります。そこは許して
もらえますか? 少なくとも自分の会社なら品質管理部から
戻されますし、そのように指導しています。個人の趣向でなく、
開発上のコーディング規約として定められているからです。


……と、あまりしゃべっては質問者様の問題解決を邪魔して
しまいそうなので。でも、「的外れ」という攻撃的な言葉、
QAサイトで使って欲しくなかったなぁ、重いっす(^^;

投稿日時 - 2010-11-09 13:35:03

ANo.6

>#5さん

今回の場合、質問者さんのfor文と#5さんのwhile文は等価です。
よって、「for文を使って無理している」という
指摘は的はずれです。

投稿日時 - 2010-11-09 12:48:52

ANo.5

・結果が不安な場合であれば、ファイルに吐き出して
確認した方が安心できます。今回のように、出力される
データ数が多い場合は特に……です。

・for文の条件部に少数を使うのは、文法的には間違えて
いないのですが、一般的には避けたほうが無難かと。
「ああ、随分無理してるなぁ」という印象です。

「繰り返し文」との事ですので、for文限定という事じゃ
ないですよね? 今回の件は、無理にfor文を使うよりも
wihle文にした方が素直だと思いますよ。

double x = 0.0;
while(x <= 5.00)
{
printf("%lf\n", (x*x*x)+(2*x)-1);
x += 0.01;
}

学校の問題であれば、単純にコレでOKですね。
※カッコは不要ですがあえて付けています。単に可読性を上げる為です。

投稿日時 - 2010-11-09 11:41:18

ANo.3

double i は実数ですが、i=0 の 0 は実数ではなく整数です。for (i=0.0; i<=5.0;i+=0.01) で試されてはいかがでしょう。





参考までに、よくある実数桁落ち誤差エラーを配慮した重み(+STEP/100.0)付きプログラム例

#include <stdio.h>
#define formula(x) x*x*x+2*x-1
#define STEP 0.01

int main(void)
{
double x;
for(x=0.0;x<=5.0+STEP/100.0;x+=STEP)
printf("%lf(%.2f) ",formula(x), x);
printf("\n");

return 0;
}

投稿日時 - 2010-11-09 09:02:57

ANo.2

余談だけど, 計算誤差を考慮すると「i+=0.01」を繰り返すのはあんまりよくない. インデックスとしてはなるべく整数を使うべし.

投稿日時 - 2010-11-09 00:49:36

ANo.1

こちらでは、正常に出力されましたが?

行数が多くて、最初の部分がスクロールアウトしてしまい表示できない、ということでは?
この計算では全部で501行、11.28...は203行目にあります。

終了後のプロンプト表示とか考えたら、使ってる表示デバイス(なんかの端末ソフトなのか、IDEの出力ウィンドウなのか)が300行しか表示できないってことはないですか?

投稿日時 - 2010-11-08 23:57:52

あなたにオススメの質問