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

Posted

技术标签:

【中文标题】VBA中最大可能的十进制值是多少?【英文标题】:What is the largest possible decimal value in VBA? 【发布时间】:2019-02-05 12:45:21 【问题描述】:

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


问题是,有点棘手,因为没有Decimaldata-type! 最接近有效小数的是 CDec() 定义的函数:

返回作为表达式结果的十进制数据值 强制转换为十进制

所以很自然,我认为任何潜在的溢出值都会被强制到最大可实现的Decimal。我尝试从MSDN Documentation 插入最大十进制vb.net 值

但请注意,这是真的,因为尝试这样做会导致溢出:

那么如何计算最接近十进制最大值的近似值呢?我尝试了这个“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,而不用过多关注计算。

所以,

    如何计算它? 我们可以传递给CDec() 函数的最大可能表达式是多少?

【问题讨论】:

bettersolutions.com/vba/functions/cdec-function.htm Does this help? 一个 IDE 错误? - 我输入Debug.Print CDec(79228162514264337593543950335),当我点击离开该行时IDE会自动将其转换为Debug.Print CDec(7.92281625142643E+28)(双文字,因为没有十进制文字ofc)如果我按F5运行我得到一个溢出 i> 错误(不正确)。如果我回到该行,删除并重新输入 CDec 然后 F5 再次运行它可以工作并打印 79228162514264300000000000000 【参考方案1】:

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

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

由于您无法在 VBA 中显式声明 Decimal,因此 CDec(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

【讨论】:

Declare PtrSafe 可能是 Private ;-) ..也可能需要用 #If VBA7 包装,如果代码为 VBA6,则另一种 Declare(不是 PtrSafe)需要在旧版本中正确编译和运行。在#Win64 下,可以使用LongLong 来稍微简化逻辑。不过可能不值得。 @MathieuGuindon 已修复。 ;-)【参考方案2】:

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

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

如您所知:79228162514264337593543950335

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

您不会将 Variant 变成常量,但 String 可能会为您做些什么?

如何计算?

喜欢:

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() 函数的最大可能表达式是多少?

如上

【讨论】:

以上是关于VBA中最大可能的十进制值是多少?的主要内容,如果未能解决你的问题,请参考以下文章

经纬度十进制值是多少

JAVA中 x=10035 x值是多少,计算步骤是啥?

字符c的ASCII码值是多少

GS1 FNC1 字符的实际十六进制/二进制值是多少?

26进制中的xfd转化为十进制为多少方法是?

十进制纬度/经度度的最大长度?