C言語今更再認識: 誤った計算結果になる | 技術日誌

技術日誌

ここでは,電子工作,木工などの趣味での記録を書いています。
なお当初はKMK研究所のメインテーマであるSPSのノウハウを書いてきましたが,順次SPSノウハウのページに複製を作っていきます。

 下の画像は,C言語でaをiの2乗とjの2乗で割る計算です。1行目がa, i, jの値です。2行目はa/(i*i*j*j)という式を入れてみた結果です。答えは0.7になるはずで,誤って計算されています。C言語の変数には型があり,aは倍精度実数型,iとjは倍精度整数型です。システムが勝手に型変換をしてくれますが,3行目ではaの型に合わせるため,明示的に(i*i*j*j)の計算結果を倍精度実数型に変換しています(括弧の前に括弧付きでdoubleと入れているのが変換です)。しかし,計算結果は0.7にはなりません。実は倍精度整数型は十進10桁程度が上限です。i*i*j*jはそれを超えています。C言語では,桁を溢れても知らん顔して(?) 処理を続けてしまいます。一方,倍精度実数型では17桁程度の精度がありますので,整数型を計算前に実数型にしておけば大丈夫です。それが4行目です。正しく0.7と答えを出しています。

 昔,FORTRANで4次式の最小二乗法で解が十幾つ(じゅういくつ)かの値のはずが,10万以上の値になってしまったことを思い出しました。数値を4乗,5乗することによりすごく大きな値になり,解はその大きな値の間の差だったのです。兎に角,計算制度を念頭に置いてプログラムを作らなければならないという教訓でした。