方法について尋ねていたこのSOの質問に出くわしました大きい16進値を正の数値に変換するには:

?Val("&H8000") -32768 Val("&HFFFF") -1 

私の答えは、文字列の数字を1つずつ繰り返し、それぞれの値を計算して結果にすることでした。

Function ConvertHex(ByVal value As String) As Double If Left(value, 2) = "&H" Then value = Right(value, Len(value) - 2) End If Dim result As Double Dim i As Integer, j As Integer For i = Len(value) To 1 Step -1 Dim digit As String digit = Mid$(value, i, 1) result = result + (16 ^ j) * Val("&H" & digit) j = j + 1 Next ConvertHex = result End Function 

機能しますが、できます。」私が「かなり単純なはずの何かのために愚かな過度に複雑なことをした」と考えるのを助けてください。

もっと良い方法がありますか?

コメント

  • I '何を達成したいかについて混乱しています。 "ダブル"は通常、64ビット浮動小数点数を意味します。それでも、テキストには"正の数値"が必要であると書かれていますが、例では署名済み 16ビット整数(通常は" short "と呼ばれます)。さらに、16進文字列では整数のみを表すことができるように思われるため、戻り値の型はShortIntegerLongUShortUIntegerULong、またはDecimal
  • @ 200_success 'のデータ型。符号なしの型はありません…
  • マット、'のCdbl("&HFFFF")の何が問題になっていますか?
  • @Meehowは、このシナリオでCDblが間違っていると思う理由についての私の回答の更新を参照してください。
  • @Meehow それは正確に" I 'で意味したことは、かなり単純なはずの何かのために、ばかげて複雑すぎることをしたことです" 😉

回答

は16進リテラルです。

式を変換できる変換関数の数があります。

したがって、目的のタイプに応じて、単純に次のようになります。

Function ConvertHex(ByVal value As String) As Currency Dim result As Currency result = CCur(value) If result < 0 Then "Add two times Int32.MaxValue and another 2 for the overflow "Because the hex value is apparently parsed as a signed Int64/Int32 result = result + &H7FFFFFFF + &H7FFFFFFF + 2 End If ConvertHex = result End Function 

現在の値と2倍の値

正確に表現できる最大の正の整数値:

  • &H0020000000000000(9,007,199,254,740,992)for ダブル( IEEE 754 binary64
  • &H000346DC5D638865(922,337,203,685,477)for 通貨

では、後者がより広い範囲の整数で機能するのに、なぜDoubleではなくCurrencyを使用するのでしょうか。

Currency常に正確です。 Currencyの値をオーバーフローさせると、エラーが発生します。 doubleの表現可能な最大整数値をオーバーフローすると、おおよその整数値が得られます。

Dim doubleMax As Double Dim doubleAfter As Double doubleMax = CDbl("&H0020000000000000") doubleAfter = doubleMax + 1 MsgBox "Double before: " & Format(doubleMax, "#") & vbNewLine & "after: " & Format(doubleAfter, "#") Dim currencyMax As Currency Dim currencyAfter As Currency currencyMax = CCur("&H000346DC5D638865") currencyAfter = currencyMax + 1 MsgBox "Currency before: " & Format(currencyMax, "#") & vbNewLine & "after: " & Format(currencyAfter, "#") 

この例の出力は次のとおりです。

 Double before: 9007199254740990 after: 9007199254740990  

次にrun-time error "6": Overflowこれは丸め誤差を避けたい。現在MSDNは、Double

IEEE 64ビット(8バイト)浮動小数点数として格納されていると主張しています

ただし、 IEEE 754 binary64 について何か読んだことがある場合は、この例の出力には少し驚いています。実際の最大値は&H00038D7EA4C68000(1,000,000,000,000,000)です。

コメント

  • すごい!' SOの回答を編集して、この回答にリンクしました:-)
  • Doubleを少し比較して、何か面白いものを発見しました。
  • doubleMax + doubleMaxを投げてオーバーフローエラー?
  • @Meehowテストしたところ、VBAのDoubleはオーバーフローしましたが、'はまだ解析結果が整数の場合、オーバーフローすることはできません。' mよかったです'その言語で動作する必要はありません。
  • これを行う正しい慣用的な方法は、@ MeehowがOPについてコメントしたように、組み込みの変換関数の1つを使用することです。 -'何が原因でこの関数を作成したのかわかりません…

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です