質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

Q&A

解決済

5回答

4591閲覧

Excel VBAでのDoubleで "0.8+0.4 = 1.2" の真偽値がfalse になる

shiku

総合スコア16

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

マクロ

定義された処理手続きに応じて、どのような一連の処理を行うのかを特定させるルールをマクロと呼びます。

0グッド

0クリップ

投稿2019/08/30 01:28

ExcelVBAのコードにて下記のようなコードを書き実行しました

VBA

1Sub tes() 2 Dim a As Double 3 Dim b As Double 4 a = 0.8 + 0.4 5 b = 1.2 6 If a = b Then 7 Debug.Print "同じ" 8 Else 9 Debug.Print "違う" 10 End If 11End Sub

これを実行したところ 違う が出力されます。
デバックで止めてaとbの値を確認したところ、間違いなくaもbも1.2だったのですが
なぜか a = b の 結果がfalseになります。

これはどうしてfalseになるのでしょうか?
また、どうすればa = b の結果をtrueにすることができるでしょうか

Windows 10で
Excelのバージョンは
Microsoft Office Professional Plus 2010
14.0.7232.5000(32ビット)
です。
よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

m.ts10806

2019/08/30 01:33

不思議ですね a = (3.6 / 3) は「同じ」
m.ts10806

2019/08/30 01:34

a = (1.2 * 1) も「同じ」
退会済みユーザー

退会済みユーザー

2019/08/30 01:47

変数に格納するだけで、値は変わってしまうのがVBAの世界。
guest

回答5

0

ベストアンサー

間違いなくaもbも1.2だったのですが

おそらく、表示段階で丸められています。厳密には異なる値となっています。そもそも、Double型は1の位以下も2進法で表しているため、0.41.2といった値を正確に表現することができません。

どうすればa = b の結果をtrueにすることができるでしょうか

演算範囲にもよりますが、Currency型(固定小数点数)やDecimal(10進数の浮動小数点数、Variantに入れる必要あり)などを使うことで回避することも考えられます。

投稿2019/08/30 01:34

maisumakun

総合スコア145121

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2019/08/30 01:35

手元のJavaScript(数値型はExcelのDoubleと同じ)で計算してみたところ、0.4+0.8の結果は「1.2000000000000002」と出ました。
m.ts10806

2019/08/30 01:50

Debug.Printでa出すと全部1.2となるところが厄介ですね。
maisumakun

2019/08/30 02:05

JavaやJavaScript、Rubyなどは「異なる浮動小数点数は異なる文字列に変換する」のがデフォルトになっているので見えない誤差というのは生じづらいですが、VBAやC#、PHPなどでは無指定で文字列に変換すると、異なる値が丸められて同じ文字列を生成することが起きてしまいます。
shiku

2019/08/30 04:58

ご回答ありがとうございます。詳しくご説明ありがとうございます。 もともとはセルの値を配列に取得したものを比較して同値かどうかを調べていました。 Currency型へキャストしたところ問題なく動かすことができました。 ありがとうございました
guest

0

回答というより「こんな感じになってますね」的な報告になってしまいますが

計算式結果
a = (3.6 / 3)同じ
a = (1.2 * 1)同じ
a = (1.1 + 0.1)違う
a = (1.2 + 0)同じ
a = (0.9 + 0.3)同じ
a = (0.6 + 0.6)同じ
a = (0.4 + 0.8)違う
a = (0.6 * 2)同じ
a = (0.4 + 0.8) * 1違う
a = (3.6 / 3) * 1同じ
a = (0.4 * 3)違う
a = (0.8 / 2 * 3)違う
a = (0.6 / 2 * 4)同じ
a = (0.8 * 3 / 2)違う
a = (0.2 * 6)違う
a = (0.2 * 2 * 3)違う
a = (0.1 * 12)違う
a = (0.3 * 4)同じ
a = (0.01 * 120)同じ
a = (0.08 * 30 / 2)同じ
a = (0.08 + 0.04) * 10同じ
a = (0.08 * 10) + (0.04 * 10)同じ

「おい」「えっ」てなりますよね。そりゃ。

演算誤差とかですかね。たぶん。
VBA VBAでも発生する演算誤差をリテラル文字で解決する

投稿2019/08/30 01:48

編集2019/08/30 01:54
m.ts10806

総合スコア80765

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shiku

2019/08/30 04:48

ご回答ありがとうございます! かなり混乱しました
m.ts10806

2019/08/30 04:50

色々検証してみるとそこから解決の糸口やキーワードが見つかるよという例でした。 今後は私が提示した回答のように考えられるパターンをたくさんやってみてください
guest

0

投稿2019/08/30 01:37

編集2019/08/30 01:45
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shiku

2019/08/30 04:49

ご回答ありがとうございます。 参考にさせていただきます。
guest

0

コンピュータの中では、Doubleの変数と言えども2進数で表現されます
ところが、ニンゲンが認識する数値というのは10進数です
この、10進数と2進数の変換のところで違いがでてくるんですね。

実のところ、あなたの見ている1.2 というのは、正確には1.2ではないです。

ということで、Doubleの数値の=の比較は行わないようにしたほうがいいです

提示のコードの問題なら、全部の数値を10倍にしといて、整数で比較すればどうでしょう。
そうすれば誤差は出ません

投稿2019/08/30 01:36

y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shiku

2019/08/30 04:49

ご回答ありがとうございます。 Doubleの問題でしたか… これから気を付けます!
guest

0

vba

1 2Sub tes() 3 Dim a As Currency 4 Dim b As Currency 5 a = 0.8 + 0.4 6 b = 1.2 7 If a = b Then 8 MsgBox "同じ" 9 Else 10 MsgBox "違う" 11 End If 12End Sub 13

型の宣言をCurrencyにして下さい。

投稿2019/08/30 01:52

編集2019/08/30 03:49
nanami12

総合スコア1015

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

shiku

2019/08/30 04:48

ご回答ありがとうございます!
nanami12

2019/08/30 04:59

詳細は、以下のページで確認できます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問