- PR -

Int関数について

投稿者投稿内容
のり
会議室デビュー日: 2007/03/15
投稿数: 12
投稿日時: 2008-03-25 11:59
VB6で開発をしております。

2つのテキストに入力された値を足し、その値に0.15をかけ、小数点を
切り捨てて単価を出しています。
小数点の切捨てのために、int関数を使用していますが、正常に動作を
してくれないのでご教授お願いします
コードは以下のようになっています
rs!Tanka = Int((Val(txt_Front.Text) + Val(txt_Rear.Text)) * 0.15)

txt_Front.Text=3178
txt_Rear.Text=1782
の場合、
Int((3178+1782)*0.15)
なので744にならなければいけないはずが
743になってしまいます。
Int関数の使い方がおかしいのでしょうか?
よろしくお願いします
むーみん
常連さん
会議室デビュー日: 2005/06/23
投稿数: 41
投稿日時: 2008-03-25 12:06
こんにちは

(Val(txt_Front.Text) + Val(txt_Rear.Text)) * 0.15

の部分の計算を一旦Currency型の変数に代入してから

Int(変数)

だとできたような気がします。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2008-03-25 13:24
Currency でなくても良いですから変数に計算結果を格納しましょう。

コード:

    Dim lFront  As Long
    Dim lRear   As Long
    Dim dTemp   As Double
    Dim lResult As Long

    lFront = 3178
    lRear = 1782

    dTemp = (Val(lFront) + Val(lRear)) * 0.15
    lResult = Int(dTemp)

    Call MsgBox(CStr(lResult))


これなら 744 になるハズです。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Blue
大ベテラン
会議室デビュー日: 2005/09/12
投稿数: 230
お住まい・勤務地: 知っている人は知っている
投稿日時: 2008-03-25 13:42
CDblをかますのはどうでしょうか?

rs!Tanka = Int(CDbl((Val(txt_Front.Text) + Val(txt_Rear.Text)) * 0.15))

追記

消費税計算だったら誤差はまずいのでCCurを使うのが妥当ですね。

rs!Tanka = Int(CCur((Val(txt_Front.Text) + Val(txt_Rear.Text)) * 0.15@))


[ メッセージ編集済み 編集者: Blue 編集日時 2008-03-25 13:47 ]
もとはーどや
会議室デビュー日: 2008/03/26
投稿数: 2
投稿日時: 2008-03-26 22:18
初めて書き込みさせていただきます。
もし、すでに解決されているのなら、読み飛ばしてください。
引用:
Int((3178+1782)*0.15)
なので744にならなければいけないはずが
743になってしまいます。
Int関数の使い方がおかしいのでしょうか?


Int関数がおかしいのではなく、"0.15"が問題なのです。
VBやCなどのプログラミング言語は、内部では2進数で表現します。
"0.15"という小数は2進数で表現すると無限小数になるはずです。
したがって、"0.15"は、2進数表現では十進数表現の"0.15"より小さい値となります。

引用:
rs!Tanka = Int((Val(txt_Front.Text) + Val(txt_Rear.Text)) * 0.15)



この式は、

rs!Tanka = (Val(txt_Front.Text) + Val(txt_Rear.Text)) * 15& / 100

というように、整数型だけで演算すれば、期待通りの結果となるはずです。
rain
ぬし
会議室デビュー日: 2006/10/19
投稿数: 549
投稿日時: 2008-03-27 09:56
VB.NET(Visual Studio 2003 および 2005)で同じコードを書いて試してみたのですが、
いずれも744.0という結果が得られました。
コード:
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        Dim tanka1 As Single = Int((Val(txt_Front.Text) + Val(txt_Rear.Text)) * 0.15)
        Dim tanka2 As Double = Int((Val(txt_Front.Text) + Val(txt_Rear.Text)) * 0.15)

    End Sub



自分は2進数については理解しているつもりですが、
VB6だけ結果が違うのは他にも何か理由があるのではないでしょうか。

自分でも調べてみて以下の過去スレッドを見つけたりしたのですが、
原因についてはいまひとつよく理解していません。
http://hanatyan.sakura.ne.jp/logbbs1/wforum.cgi?mode=allread&no=3276&page=0
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-03-27 15:54
引用:

のりおだすさんの書き込み (2008-03-25 11:59) より:
rs!Tanka = Int((Val(txt_Front.Text) + Val(txt_Rear.Text)) * 0.15)


まず、内部2進数表現で値を保持する小数を扱う場合、2進数←→10進数変換に伴う誤差の発生は起こりうるものだとしてコーディングすべきです。
すなわち、提示されたコードのように 0.15 をかけた段階で誤差が起こるかもしれないと考え、その誤差込みの微妙な値を Int で切り捨てるようなことはしないのが大前提です。Double 型を使わないとか、四捨五入のような丸めを使うとか、掛けて割るみたいなことをするなど、いろいろなテクニックはあります。

それとは別に、VB の挙動として、小数の値がなんか変ですね。
つぎのようなコードで試してみました。(VB5CCE を使用。)

コード:
Option Explicit

Private Sub Command1_Click()
    Dim k As Double
    k = 744
    Dim a As Double
    a = 4960
    Dim b As Double
    b = 0.15
    Dim c As Double
    c = a * b
    Dim d As Double
    d = Int(c)
    Dim e As Double
    e = Int(a * b)
    
    Debug.Print "c = " & c & ", d = " & d & ", e = " & e
    
    If c < k Then
        Debug.Print "c < k"
    ElseIf c = k Then
        Debug.Print "c = k"
    ElseIf c > k Then
        Debug.Print "c > k"
    Else
        Call Err.Raise(60000)
    End If

    If d < k Then
        Debug.Print "d < k"
    ElseIf d = k Then
        Debug.Print "d = k"
    ElseIf d > k Then
        Debug.Print "d > k"
    Else
        Call Err.Raise(60000)
    End If

    If e < k Then
        Debug.Print "e < k"
    ElseIf e = k Then
        Debug.Print "e = k"
    ElseIf e > k Then
        Debug.Print "e > k"
    Else
        Call Err.Raise(60000)
    End If
End Sub


すると、結果はつぎのようになりました。
コード:
c = 744, d = 744, e = 743
c = k
d = k
e < k


すなわち、
c = a * b
d = Int(c)

e = Int(a * b)
で結果が異なるのです。

私も VB を長いこと使っていますが、良く分かりません。最適化云々のため?
そもそも言語仕様が明確ではないため、Int(c) と Int(a * b) のなにが違うのか、や、a * b の型はなんなのか、が、分かりません。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2008-03-27 16:00
引用:

rainさんの書き込み (2008-03-27 09:56) より:
自分でも調べてみて以下の過去スレッドを見つけたりしたのですが、
原因についてはいまひとつよく理解していません。
http://hanatyan.sakura.ne.jp/logbbs1/wforum.cgi?mode=allread&no=3276&page=0


さきほど、このリンク先を読まずに書いてしまいましたが、そこに書いてありましたね。
私はVBの「バグ」(か、どうしようもないけったいな仕様)だと思います。

スキルアップ/キャリアアップ(JOB@IT)