VB6 小数点以下を含む数値計算について
VB6で小数点以下を含む数値計算で正確な値を求めるには浮動小数点型ではなく通貨型や十進型を使用したほうが良いです。
(1)(2)(3)は正確な値になりません。
(例)
(1)(2)(3)は100×66.96が6695になってしまう。
(1)
dim curKingaku as double
dim a,b as double
a = 100
b = 66.96
curKingaku = Fix(A * B)
(2)
dim curKingaku as double
dim a,b as double
a = 100
b = 66.96
curKingaku = a * b
curKingaku = Fix(curKingaku)
(3)
dim curKingaku as currency
dim a,b as double
a = 100
b = 66.96
curKingaku = Fix(a * b)
正確に数値にする方法
dim curKingaku as currency
dim a,b as currency
a = 100
b = 66.96
curKingaku = a * b
curKingaku = Fix(curKingaku)
dim varKingaku as variant
dim a,b as variant
a = 100
b = 66.96
varKingaku = cdec(a) * cdec(b)
varKingaku = Fix(cdec(curKingaku))
« SQL-Server2000 INSERT時の連番取得方法 | トップページ | C# ASP.NETでエラーログファイルを出力する方法 »
「VB6」カテゴリの記事
- VB6 DataGirdでデータが表示されない(2010.11.05)
- VB6 コレクション(2007.08.28)
- VB6 On Error Resume Nextが動作しない(2007.06.27)
- VB6 PDF自動印刷(調査中)(2006.09.05)
- FAX送信 続き(2006.09.04)
コメント
« SQL-Server2000 INSERT時の連番取得方法 | トップページ | C# ASP.NETでエラーログファイルを出力する方法 »
たまたま本記事を目にしましたので、勝手に投稿させていただきます。
1)浮動小数点型では正確に計算できないとの問題提起ですが、整数変換の関数Fixが不適切ではないでしょうか。Fixは小数点以下を切り捨てますので、正確な値にはなりません。
2)関数Fixの代わりに関数CIntを使用すれば正確な値になるはずです。CIntは小数点以下を四捨五入しますので、数学的に正しい整数値に変換されます。
3)通常、特別な理由がない限り、関数Fixでなく、関数CIntを使用した方がよいです。
投稿: 黒田 英夫 | 2011年7月28日 (木) 09時54分
1)説明が不足して申し訳ありません。
「数値計算して小数点以下を切り捨てした結果」の一文が抜けていました。
2)-32,768 ~ 32,767の数値を扱う場合はCint、それ以上の数値の場合は、Clngでしょうか。
しかし、CIntですと以下のようなケースが気になりました。
Dim a As Integer
a = CInt(0.5)
Debug.Print a
変数aの私が期待する値は1ですが、実際は0になります。
※CIntの仕様
小数部分がちょうど 0.5 の場合、最も近い偶数に値を丸めます。
投稿: tukaenai-pg | 2011年8月 3日 (水) 18時49分
整数に丸める問題について補足意見を述べさせていただきます。
1)CInt(0.5)が0になることは、0.5が1よりも0に近いためと考えられます。文字通りの四捨五入になりませんが、私は自然と思います。
◇四捨五入で0.5を1にすることはおかしく、小数点2桁目以下がない場合は五捨六入が正しいという考え方もあります。
注)工学分野では、四捨六入とし、.5を超えた場合は切り上げるのが一般的と思います。
2)小数点1桁目が5付近のコンピューター誤差の問題を解決するため、微小値を加える方法があります。たとえば、aを整数、bを浮動小数点数として、次のように記述します。
a = CInt(b + 0.0001)
3)上記の微小値を加える方法は、私自身、画面の座標位置を設定する処理で実用しています。画面の座標位置は整数ですから、このような方法を用いないと、1ピクセルのずれが生じるます。
◇別々に計算された同一点の小数点値が0.5と0.5000001になった場合、0と1という違った座標値になることを避けるためです。
投稿: 黒田 英夫 | 2011年8月 5日 (金) 23時20分
<訂正>
すみませんが、先の投稿を少し訂正させていただきます。1)項の「0.5が1よりも0に近いため」というのは感覚的なもので申し訳ありません。数学的に0.5が0と1の中間であることは当然です。ただ、0から1へ進む自然な向きの場合、0.5未満の位置では0の方に近い状態であり、1に近い状態に変化するのは0.5を超えてからという程度の意味合いです。
投稿: 黒田 英夫 | 2011年8月 6日 (土) 00時38分
いろいろ勉強になります。ありがとうございます。
四捨五入についてwikiで調べてみましたが、以下の大きく2パターンがあるようです。
■JIS Z 8401 規則A
端数が0.5より小さい場合切り捨て、端数が0.5より大きい場合切り上げ、
端数がちょうど0.5なら切り捨てと切り上げのうち結果が偶数となる方へ丸める
■JIS Z 8401 規則B
端数が0.5未満なら切り捨て、0.5以上なら切り上げる
Cintの仕様は規則Aに近いと思われます。
(VB6コード例)
Dim a As Integer
a = CInt(0.5)
Debug.Print a
→結果:0
a = CInt(1.5)
Debug.Print a
→結果:2
a = CInt(2.5)
Debug.Print a
→結果:2
規則A、Bは使用する場面において使い分ける必要がありそうです。
投稿: tukaenai-pg | 2011年8月17日 (水) 11時47分
当方の認識不足で申し訳ありませんでした。確かにCIntで5を切り上げているかどうかは、上位が偶数になるようにされています(VB2010で確認)。私が昔、JIS Z 8401 規則Aを習い憶えたことをすっかり忘れていて、この機会に思い出させていただきました。その規則Aが工学分野では最も適用されていると思います。
VBを使用するとすれば、原則はCIntの通りでよく、特別に必要な場合は規則Bとなるようにプログラム処理すればよいと思います。いずれにしても、コンピューター誤差を考慮しておくことが大切です。
どうもありがとうございました。
投稿: 黒田 英夫 | 2011年8月25日 (木) 00時58分