Cint と Fixの違いについて


mari  2007-07-06 02:49:55  No: 136921

困ったことが起きてます・・・・

Dim  下代  as  Long
Dim  上代  as  Long
Dim Rate As Long

'掛率58の場合
Rate = ItemTextBox(0).Text
' 上代5700円×掛率58%の場合の下代は3306円               
【1】下代 = CInt((上代 * (Rate * 1 / 100)))
【2】下代 = Fix((上代  * (Rate * 1 / 100)))

【1】の答えが3306
【2】の答えが3305  になってしまいます。

【1】はコメント行にしてて
ずーっと【2】でプログラムを運営してました。

ある日、上代が5700円の場合下代が正しく入らないことに気づきました。
fixとCintの違いを調べなおしました。
http://park5.wakwak.com/~weblab/refFixInt.html
負の数はRateに入りません。

少数になった場合は切り捨てしたいのです。

しかも、2回目このルーチンに入ると【2】は3306円になります????

Fixではなくて、Cintで、いいのでしょうか?


魔界の仮面弁士  2007-07-06 10:42:53  No: 136922

> 【1】下代 = CInt((上代 * (Rate * 1 / 100)))
> 【2】下代 = Fix((上代  * (Rate * 1 / 100)))
うーん。幾つか問題があるような。
# とりあえず、括弧の数が余計なのは無視するとして。

(1) 変数名について
旧 VB においては、日本語の変数名は基本的に NG です。
http://support.microsoft.com/kb/418924
現 VB においては、日本語の変数名も許可されています。
http://support.microsoft.com/kb/921451

とりあえず今回は、.NET 開発であるものと仮定して回答します。

(2) 演算処理とデータ型について
除算演算子「/」による計算結果は、「浮動小数点型」の値となります。
(結果が浮動小数とならない唯一の例外は、Decimal 型を対象にした場合です)

浮動小数点型はその特性上、誤差を含みやすい型であり、金額計算には向きません。
たとえば、0.1 や 0.3 といった値の保持には、僅かな誤差を生じますので御注意を。
# 内部 2 進数で保持される関係上、0.5 や 0.25 などといった値ならば問題が無いのですが。

(3) 使用している関数とデータ型について
Rate変数(Long型)に、Textプロパティ(String型)を入れている点には目を瞑るにしても…。

【1】の CInt は「型変換関数」であり、結果を Integer 型にします。
しかし、変数[下代]は Long 型です。両者の型が一致しないので、適切なコードとはいえないでしょう。
CLng を使うか、[下代]を Integer にするべきかと。

ちなみに、Int 関数や Fix 関数は、型の変換は行いません。
先の(2)にも書いたように、今回の演算式は Double 型の値を返しますので、
【2】の場合、Fix しても、その結果は Double 型のままとなっています。

> ずーっと【2】でプログラムを運営してました。
運営 → 運用、かな。

> 負の数はRateに入りません。
……?
もしかして、Int 関数と CInt 関数を混同していたりはしませんか?

> Fixではなくて、Cintで、いいのでしょうか?
どちらも NG です。
そもそも、演算途中で Double 型が使われてしまっているため、
計算結果自体が、ごく僅かな誤差を含んだ値になっています。(この時点で既に手遅れです)

誤差を含んだ値に対して丸め/切捨てを行ったところで、1円程度の誤差が
含まれてしまう可能性は出てきてしまいます。

この場合は、誤差を含まないよう、演算値をすべて Decimal 型に統一するとか、あるいは、
数式を見直して、除算無しの整数演算だけで済ませるなどの対策が必要です。
丸めの問題はその後の話。


mari  2007-07-07 00:06:15  No: 136923

お世話になります。
私、基本がなってないような・・・魔界の仮面弁士 さまのカキコミを
1行1行理解していきたいと思います。

ちなみにVB6.0  SP?←最新  です。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加