VBA 中最大可能的十进制值是多少?

What is the largest possible decimal value in VBA?

我一直在尝试在 中创建类似于 DEC_MAX 常量的东西。


问题是,这有点棘手,因为没有Decimal数据类型!
最接近功能小数的是 CDec() 定义的函数:

Return the Decimal data value that is the result of Expression being Let-coerced to Decimal

所以很自然地,我认为任何可能溢出的值都会被强制到可实现的最大值 Decimal。我尝试插入最大小数 value from MSDN Documentation

但是请注意,这样做会导致溢出:

那么在这里如何计算最接近十进制最大值的近似值呢?我试过这个 "computer-bricking" 丑陋的代码循环:

Private Sub brick_my_Excel()
  On Error Resume Next
  x = 79228162514264337593543950335 'let's let it auto-coerce i guess
  Do 
     Debug.Print(x)
     x = x - 1
  Loop
End Sub

然而,这完全抑制了溢出,以几乎类似字符串的方式打印 x,而没有过多关注计算。

所以,

  1. 如何计算它?
  2. 我们可以传递给 CDec() 函数的最大可能表达式是什么?

我能弄清楚如何做到这一点的唯一方法是完全绕过 VBA 和 "build" 内存中的最大值。 The DECIMAL structure为16字节,定义为:

typedef struct tagDEC {
  USHORT    wReserved;
  BYTE      scale;
  BYTE      sign;
  ULONG     Hi32;
  ULONGLONG Lo64;
} DECIMAL;

由于您无法在 VBA 中显式声明 DecimalCDec(0) 将为您提供一个具有正确 Variant 类型的供您使用。符号和比例独立于 12 字节值,因此只需设置该内存区域中的所有位即可获得最大值(最大值的比例为 0):

#If VBA7 Then
    Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias _
        "RtlMoveMemory" (Destination As LongPtr, Source As Any, _
        ByVal length As Long)
#Else
    Private Declare Sub CopyMemory Lib "kernel32" Alias _
        "RtlMoveMemory" (Destination As Long, Source As Any, _
        ByVal length As Long)
#End If

Private Const VT_DECIMAL As Integer = &HE
Private Const BIT_MASK As Long = &HFFFFFFFF
Private Const DATA_OFFSET = 4
Private Const SIZEOF_LONG = 4

Public Function MaxDecimal() As Variant
    'Get a decimal to work with.
    Dim dec As Variant
    dec = CDec(0)

    Dim vtype As Integer
    'First 2 bytes are the VARENUM.
    CopyMemory ByVal VarPtr(vtype), ByVal VarPtr(dec), LenB(vtype)

    'Make sure the VARENUM is a VT_DECIMAL.
    If vtype = VT_DECIMAL Then
        'Fill the top 12 bytes of it's data area with truthy bits
        CopyMemory ByVal VarPtr(dec) + DATA_OFFSET, BIT_MASK, SIZEOF_LONG
        CopyMemory ByVal VarPtr(dec) + DATA_OFFSET + SIZEOF_LONG, BIT_MASK, SIZEOF_LONG
        CopyMemory ByVal VarPtr(dec) + DATA_OFFSET + SIZEOF_LONG * 2, BIT_MASK, SIZEOF_LONG
    End If

    MaxDecimal = dec
End Function

请注意,这显然不会为您提供 Const,但它确实为您提供了正确的最大值:

Public Sub Test()
    MsgBox MaxDecimal
End Sub

我不确定问题是什么,因为有很多 intentions/questions 提出:

What is the largest possible decimal value in VBA?

如你所知:79228162514264337593543950335

I've been trying to create something similar to a DEC_MAX constant in vba.

您不会将 Variant 转化为常量,但 String 可能适合您?

How would one go about calculating it?

喜欢:

Public Const MAX_DEC_STRING = "79228162514264337593543950335"

Public Function MAX_DEC() As Variant
    MAX_DEC = CDec(MAX_DEC_STRING)
End Function

Sub test()
    Dim v As Variant, x As Variant
    v = MAX_DEC
    x = CDec("79228162514264337593543950334")   '7922816251426433759354395033

   MsgBox v - x
End Sub

What is the largest possible expression we can pass to the CDec() function?

同上