2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

64bit VBAでHex関数に2147483648以上のCurrencyを渡すと不正確な結果となる

Last updated at Posted at 2023-12-26

内容

Hex関数に2147483648(2の31乗 =VBAのLong型 = 符号付き32bit整数の最大値+1)以上の値のCurrency型の値を渡すと、本来の値より1大きい16進数表記の文字列となる。

サンプルコード

Sub SampleCurrencyHex231226()
    Dim c As Currency, l As LongLong, d As Double
    c = 2 ^ 31 - 1
    l = 2 ^ 31 - 1
    d = 2 ^ 31 - 1
    
    Dim v As Variant
    For Each v In Array(c, l, d)
        Debug.Print TypeName(v), v, Hex(v)
    Next v
    
    c = 2 ^ 31
    l = 2 ^ 31
    d = 2 ^ 31
    
    For Each v In Array(c, l, d)
        Debug.Print TypeName(v), v, Hex(v)
    Next v
End Sub

結果

Currency       2147483647   7FFFFFFF
LongLong       2147483647   7FFFFFFF
Double         2147483647   7FFFFFFF
Currency       2147483648   80000001 '<- 1 大きい
LongLong       2147483648   80000000
Double         2147483648   80000000

備考

そもそもHex関数のページでは以下のように対応している値はLong型の範囲に制限されていることになっている。

Hex(number)
必須の 数値引数 は、任意の有効な 数値式 または 文字列式です。

number の値 Hex の戻り値
-2,147, 483,648 〜 2,147, 483,647 最大 8 桁の 16 進文字
Null Null
ゼロ (0)

実際、32bit VBAでは上記の表の通りの挙動(2147483648を指定するとエラー)となる。
手元で試した限り、64bit VBA環境であればLongLong(符号付き64bit整数)の範囲までは有効のようだった。

なぜCurrencyという通常の整数ではない型をHex関数に渡したのか

32bit整数の範囲でビット演算(色のARGBを設定するイメージ)をするときにLong型の代わりに使おうとしたため。
VBAにはビットシフト演算子が無く、符号無しの大きな整数型も無いため、32bitをフルに使うビット演算をLong型で行うのが面倒だったため、横着しようとした結果。

型の本来の用途と違う用途に使うのは注意が必要ですね、という教訓でした。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?