これは謎ですね.
math.h をインクルードしないと呼び出し元で返り値を int と判断してしまうことはありますが.
カタカナや句読点を含むと、コンパイルすら上手くいかなくなるような…
文字コードが sjis や jis だと,文字コードの一部が " とか \ とかになってしまう場合があります.
euc-jp だと,日本語文字では 8 bit めが立っているので,このような衝突はありません.
が,コンパイラや環境によっては,8 bit めを drop して判断するものもあるので,この場合はだめですね.
えっ? (スコア:0)
今リアルタイムで大学でCをやってるものですが・・・
void main(void)
むむむ、、、
Re:えっ? (スコア:0)
どうやら私が今習ってるCは相当おかしいみたいで・・・
前に課題を出されたのですが
それの解答がこれです。
http://www.geocities.co.jp/Playtown-Dice/5199/kadai13.txt [geocities.co.jp]
ここを見てるとこのソースは突込みどころ満載のようですが・・・
うーん、このまま素直にこの講義を受けるか、自分でやり直したほうがいいのか・・・
Re:えっ? (スコア:2)
私の学校の環境だけ?
#ちなみに当方、main()派。最初にそう習ったので…#1年後期以降の課題のサンプルとして配られるコードではint main(...)も多いです。
#が、自分で一から書く時には大抵main()にしてしまうです。
#まあ、プログラマーを育てる為の授業でなく、あくまで実験の道具としてのCらしいですから。
#void mainも「こういう書き方をする人もいる」と習いましたが、実際書いたことはないです。
Re:えっ? (スコア:1)
これは謎ですね. math.h をインクルードしないと呼び出し元で返り値を int と判断してしまうことはありますが.
文字コードが sjis や jis だと,文字コードの一部が " とか \ とかになってしまう場合があります. euc-jp だと,日本語文字では 8 bit めが立っているので,このような衝突はありません. が,コンパイラや環境によっては,8 bit めを drop して判断するものもあるので,この場合はだめですね.
昔,そういう環境でプログラムを書いていた時は,そのようにコンパイラで解釈されてしまう文字を \ でエスケープするプリプロセッサ(というか,プリプリプロセッサ?)を書いて,こいつに通してからコンパイルにかけてました.
が,エスケープするにしても
Re:えっ? (スコア:1)
これって「模範回答」なのでしょうか? ま,突っ込んでみましょう :-)
入力される数値の数が 3 個よりも少ない場合もあり得ます.
判別式自体は正の値なので,解の公式を計算しようとしますが,分母が 0 になるので,「0 で割り算できないぞ」例外で異常終了してしまいます.
同じ内容が繰り返し何度も出てくるのは,「駄目なプログラム」の典型的な特徴です. 修正する時のことを考えると,修正箇所が1箇所だけの方が保守は簡単ですね.
浮動小数点型の数値は変換・演算で誤差が出るので,== による比較は思ったように動かないことがあります(というか,動かない,と思った方が良いでしょう). ある程度の不正確さを容認して d*d<ε のように近似的に判定した方がいい場合が多いです. この問題の場合は微妙なところですが.
pow() 自体は,pow(2.5, 3.5) のような場合にも対応しているので,内部では exp(log(a)*b) のような計算をしてると思います. FPU によっては built-in かもしれませんが.. あと,サブルーチンコールのオーバヘッドもあります.2乗であれば,a*a のように書いた方が計算量も少なく,サブルーチンコールも生じる可能性は少ないでしょう.
これらの修正を全部行うと,「説明用」のプログラムとしてはちょっと見通しが悪くなるかもしれませんが.
まぁ,プログラム自体の評価としては,大学だと,教養部での「パソコンでプログラム書いてみましょうね」レベルの講義だったら,ま,こんなものなのかもしれません. 学部の「数値計算」の講義だとしたら…「単位をとるための講義」と割り切った方が良いでしょう.
「数値計算」の議論・技術は言語・CPU・OS を越えて(おそらく)一生ものの技能になると思います. というわけで,授業とは別に,気合いを入れて自習して身に付ける価値はあると思います.
Re:えっ? (スコア:0)
x1 = - b - sqrt(D) if b > 0
x1 = - b + sqrt(D) otherwise
としてx2は解と係数の関係を使って決める、という"常識"が指摘されていないのはいかがなものか、と思います。
Re:えっ? (スコア:1)
b と sqrt(D) の絶対値が近い場合の桁落ちを防ぐ工夫ですね. 参考になります.
もう片方の解は c/(x1*a) で求まるので,この場合,生じるのは丸め誤差だけかな.
ええと,一応説明しておくと,桁落ち,というのは,たとえばこんな感じ.
この例では,有効数字 8 桁の 2 つの数の引き算を行った結果得られる数値の有効数字が 2 桁になってしまってますね. このように絶対値が近い数で引き算を行うと,有効数字の桁数が減ってしまう現象が起きます. これが桁落ち.今の2次方程式の解の公式の例では,±√ の2つの解の片方は異符号の演算なので桁落ちの条件に引っかかりますが,もう片方は同符号の演算なので,桁落ちは発生しません. まず,この桁落ちしない方の解を採用し,もう片方の解は上記の式で導きます. この場合は乗除算だけで,丸め誤差の発生がありますが,どのみち丸めが発生するのは有効桁より下なので,有効桁数の現象は生じない,ということになります.
というところでよろしいでしょうか,先生.
Re:えっ? (スコア:2)
叩いて下さい > 識者
Re:えっ? (スコア:1)
---
char s[LINE_MAX];
double a, b, c;
int sign_of_b;
- double d;
+ double d, sqrt_d, x ;
do
{
---
---
d = b * b - 4.0 * a * c;
if (d > DBL_MIN)
{
- double sqrt_d = sqrt(d);
- double x = -sign_of_b * (b + sqrt_d) / 2.0 / a;
+ sqrt_d = sqrt(d);
+ x = -sign_of_b * (b + sqrt_d) / 2.0 / a;
printf("答え % f\n", x);
- printf(" % f\n", x + sign_of_b * sqrt_d / a);
+ printf(" % f\n", ( c / ( x * a ) ) );
}
else if (d < -DBL_MIN)
{
---
宣言文の位置は元のところにあってもいいんですけどね。