tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板
VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re: 数値の1と文字列の"1"が同じになる理由
投稿日: 2020/12/07(Mon) 12:05
投稿者魔界の仮面弁士
> 最近ExcelのVBAを少しやっています。
VB6 も VBA も言語エンジンは一緒なので、判断基準は変わりません。
VBA の最新は 7.1 なので、言語仕様的には VB6 の方が古いですが。


>   '↓本来、If CStr(b) = a Thenの様に
>   ' 型を合わせてから比較、と書くべきとは思うのですが…
>   If b = a Then  
比較式の一方が数値型で、他方が文字列型ですね。
この組み合わせの場合、両端が Double 型へと暗黙の型変換されてから比較される仕様です。

こうした変換ルールは一応ヘルプにも書いてあるのですが、ちょっと分かりにくいですよね。
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/comparison-operators


要するに今回の場合、
  If b = a Then
という処理が
  If CDbl(b) = CDbl(a) Then
に相当する判定式として処理されることになります。

そのため以下の組み合わせは、いずれも「If a = b Then」が True として判定されます。
 a = "&HA"
 b = 10

 a = "(100)"
 b = -100


一方、文字列側を数値に変換できないようなケース…たとえば
  a = ""
  b = 1
のような場合には、CDbl(a) 相当の型変換が行えないため、
VB6 や VBA では『実行時エラー '13': 型が一致しません。』
.NET 版の VB では『System.InvalidCastException: 'String "" から型 'Double' への変換は無効です。』
というエラーになります。



>     Dim a As String
>     Dim b As Integer
>     a = "1"
>     b = 1
二つの項に対する演算において、それぞれの項のデータ型が異なる場合、
それが比較演算であれ代入演算であれ算術演算であれ、まずは暗黙の型変換が働きます。

今回の場合、比較式の一方が数値型だったので、数値同士の演算として処理されたわけです。


これが代入処理であったならば、たとえば
 Dim a As String
 Dim b As Integer
 a = -1     '文字列型変数に整数値を代入 … CStr(-1) 相当で "-1"
 b = "2.5"  '整数型変数に文字列値を代入 … CInt(CDbl("2.5")) 相当で 2
 b = "3.5"  '整数型変数に文字列値を代入 … CInt(CDbl("2.5")) 相当で 2
と書いたとしても、特にエラーにはなりません。


比較演算であれ、四則演算であれ、同様の型変換が行われます。
  11  +  11  は 22     になります。
  11  + "11" は 22.0   になります。
 "11" +  11  は 22.0   になります。
 "11" + "11" は "1111" になります。
  11  &  11  は "1111" になります。
  11  & "11" は "1111" になります。
 "11" &  11  は "1111" になります。
 "11" & "11" は "1111" になります。


蛇足ですが、VBA において
  x / y
という除算演算は、基本的には Double 型として演算されます。

Debug.Print TypeName("24" / "2")         ' "Double"
Debug.Print TypeName(CCur(1) / CInt(1))  ' "Double"
Debug.Print TypeName(CLng(1) / CLng(1))  ' "Double"
Debug.Print TypeName(CCur(1) / CCur(1))  ' "Double"
Debug.Print TypeName(CDec(1) / CDec(1))  ' "Decimal"
Debug.Print TypeName(CSng(1) / CSng(1))  ' "Single"

x / y という割り算の結果は、ほとんどが Double 型となりますが、例外的な組み合わせとして
x と y の一方が Decimal の場合は、演算結果は Decimal 型になります。
x と y の一方が Single で、他方が Byte, Integer, Single いずれかなら、Single 型に演算されます。
x と y の一方または両方が Null なら、演算結果も Null です。
(なお、Empty 値を渡した場合には、数値ゼロとして扱われます)
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/forwardslash-operator


> ご享受して頂けないでしょうか。
享受:与えられたものを自分のものとして受け入れ、味わい楽しむこと
 →「インターネットの恩恵を享受する」
教授:専門的な学問や技芸を教え授けること
 →「書道を教授する」
教示:知識や方法などを教え示すこと
 →「御教示を賜りたい」
http://www.tt.rim.or.jp/~rudyard/torii009.html



> ※VB6.0や、VB2005以降だと数値と文字が違うと
VB6 やそれ以前でも同じですし、
VB.NET (2002)、VB.NET 2003、VB2005 はもちろん、
VB2008、VB2010、VB2012、VB2013、VB2015、VB2017、VB2019 でも
この点は変わっていません。

ただし .NET では、『Option Strict On』指定でコンパイルした場合には、
データ型の違いまでチェックされるようになっています。

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。