代码之家  ›  专栏  ›  技术社区  ›  Samuel Hulla

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

  •  7
  • Samuel Hulla  · 技术社区  · 6 年前

    我一直在尝试创造类似于 DEC_MAX


    问题是,这有点棘手,因为 根本没有 Decimal 数据类型
    最接近正常工作的十进制数是 CDec() 定义的函数:

    所以很自然地,我认为任何潜在的过度价值都会被最大限度地利用 . 我试着插入最大小数点 价值来自 MSDN Documentation

    但是,这是正确的,因为这样做会导致溢出:

    enter image description here

    丑陋的代码循环:

    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
    

    所以,

    1. 怎么计算呢?
    2. 我们能传递给客户的最大可能的表达是什么 CDec() 功能?
    2 回复  |  直到 6 年前
        1
  •  8
  •   Comintern    6 年前

    唯一的办法,我可以想出如何做到这一点是完全绕过VBA和“建立”的最大价值在内存中。 The DECIMAL structure

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

    因为不能显式声明 Decimal CDec(0) 会给你一个有正确答案的 Variant

    #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
    

    Maximum Decimal Value

        2
  •  1
  •   MacroMarc    6 年前

    我不确定问题是什么,因为提出了很多意图/问题:

    如您所知:79228162514264337593543950335

    我一直在尝试在vba中创建类似于DEC\u MAX常量的东西。

    您不会将变量转换为常量,但是字符串可以为您做些什么?

    怎么计算呢?

    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
    

    我们可以传递给CDec()函数的最大表达式是什么?