Какое максимально возможное десятичное значение в VBA? - PullRequest
0 голосов
/ 30 августа 2018

Я пытался создать нечто подобное константе DEC_MAX в .


Проблема в том, что это немного сложно, потому что нет Decimal типа данных !
Ближайший к действующему десятичному разряду вы можете получить функцию CDec(), которая определена:

Возвращает десятичное значение данных, которое является результатом выражения Пусть приведен к десятичному

Естественно, я думал, что любое потенциально превышающее значение будет приведено к максимально достижимому Decimal. Я попытался вставить максимальное значение Decimal из Документация MSDN

Это, однако, примечание верно, так как попытка сделать это приведет к переполнению:

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

Это, однако, полностью подавляет переполнение, печатая x почти как строковый способ, не обращая большого внимания на вычисления.

Итак,

  1. Как можно было бы рассчитать это?
  2. Какое наибольшее возможное выражение мы можем передать функции CDec()?

Ответы [ 2 ]

0 голосов
/ 30 августа 2018

Я не уверен, в чем вопрос, потому что было выдвинуто много намерений / вопросов:

Какое максимально возможное десятичное значение в VBA?

Как вы знаете: 79228162514264337593543950335

Я пытался создать нечто похожее на константу DEC_MAX в vba.

Вы не получите 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 ()?

Как указано выше

0 голосов
/ 30 августа 2018

Единственный способ выяснить, как это сделать, - полностью обойти VBA и «построить» максимальное значение в памяти. Структура DECIMAL имеет размер 16 байтов и определяется как:

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

Поскольку вы не можете явно объявить Decimal в VBA, 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

Maximum Decimal Value

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...