简体   繁体   English

MOD函数在Excel VBA中专门使用长变量

[英]MOD Function Exclusively Uses Long Variables In Excel VBA

UPDATED I'm cleaning up this post after its resolution. 更新后,我将清理该帖子。 To summarize, I was making a user defined formula for excel that calculated the next highest prime number ( =NextHighestPrimeNumber(100) returns 101 ). 总而言之,我为excel创建了一个用户定义的公式,该公式计算了下一个最高质数( =NextHighestPrimeNumber(100)返回101 )。 As I begin experimenting, I noticed the formula would error on around 2.1 billion. 当我开始进行实验时,我注意到该公式的误差约为21亿。 I assumed it might have been connected to my variable so I tried DOUBLE, but I still received errors. 我以为它可能已连接到我的变量,所以我尝试了DOUBLE,但仍然收到错误。

Here is the function: 这是函数:

Function NextHighestPrimeNumber(StartingNumber As Double) As Variant
Dim CeilingTest As Long
Dim i As Long

If StartingNumber < 11 Then
            If StartingNumber > 6 Then
                NextHighestPrimeNumber = 11

            ElseIf StartingNumber > 4 Then
                NextHighestPrimeNumber = 7

            ElseIf StartingNumber > 2 Then
                NextHighestPrimeNumber = 5

            ElseIf StartingNumber > 0 Then
                NextHighestPrimeNumber = 3

            ElseIf StartingNumber = 0 Then
                NextHighestPrimeNumber = 1

            Else
                NextHighestPrimeNumber = "Pick A Positive Integer"

            End If

        Exit Function

Else

    'Create Array
    ReDim Prime_Array(0 To 4) As Double
    GoTo StartArrayPopulate
DoneWithStartingArray:

    If StartingNumber Mod 2 = 0 Then
        StartingNumber = StartingNumber - 1
    End If

NewNumber:
        StartingNumber = StartingNumber + 2
        CeilingTest = Int(VBA.Sqr(StartingNumber))


    'Array loop
    For i = LBound(Prime_Array) To UBound(Prime_Array)
        If Prime_Array(i) > CeilingTest Then
            NextHighestPrimeNumber = StartingNumber
            Exit Function
        ElseIf StartingNumber Mod Prime_Array(i) = 0 Then GoTo NewNumber

        End If
    Next i


    'Add new Array Value
ExpandDim:
    ReDim Preserve Prime_Array(UBound(Prime_Array) + 1)
    Prime_Array(UBound(Prime_Array)) = NextHighestPrimeNumber(Prime_Array(UBound(Prime_Array) - 1))

    'test if bigger than cieling
    If Prime_Array(UBound(Prime_Array)) > CeilingTest Then
        NextHighestPrimeNumber = StartingNumber
        Exit Function

    ElseIf StartingNumber Mod Prime_Array(UBound(Prime_Array)) = 0 Then GoTo NewNumber


    Else
        GoTo ExpandDim
    End If

End If


Exit Function

StartArrayPopulate:


Prime_Array(0) = 3
Prime_Array(1) = 5
Prime_Array(2) = 7
Prime_Array(3) = 11
Prime_Array(4) = 13


GoTo DoneWithStartingArray

End Function

The issue is because the VBA MOD function ALWAYS converts the numerator to a LONG variable, even when it is previously defined as Double or is a hard coded number! 问题是因为VBA MOD函数始终将分子转换为LONG变量,即使先前已将其定义为Double或为硬编码数字!

Test yourself: 测试自己:

MsgBox (2147483647) mod 3 'Maximum Long Value

Vs. VS.

MsgBox (2147483647 + 1) mod 3'Oh False!

I used the INT function to duplicate the mod calculation Numerator -(INT(Numerator /Denominator)*Denominator) but there are a lot of other creative ways to avoid. 我使用INT函数来复制mod计算Numerator -(INT(Numerator /Denominator)*Denominator)但是还有很多其他可以避免的创造性方法。 Even Evaluate with the excel MOD function worked correctly. 甚至使用excel MOD函数进行Evaluate可以正常工作。

Bottomline: I'm never going to use MOD for any calculations that could potentially be exceeding 2 Billion 底线: 我永远不会使用MOD进行任何可能超过20亿的计算

I've cleaned up my code significantly since my first post and left the bad rows commented out that were throwing errors flagged with `zz failed code: 自从我发表第一篇文章以来,我已经大大清理了我的代码,并注释掉了那些抛出带有zz失败代码标记的错误的错误行:

Function NextHighestPrimeNumber(StartingNumber As Double) As Variant
Dim CeilingTest As Long
Dim i As Long


If StartingNumber < 11 Then
            If StartingNumber > 6 Then
                NextHighestPrimeNumber = 11

            ElseIf StartingNumber > 4 Then
                NextHighestPrimeNumber = 7

            ElseIf StartingNumber > 2 Then
                NextHighestPrimeNumber = 5

            ElseIf StartingNumber > 0 Then
                NextHighestPrimeNumber = 3

            ElseIf StartingNumber = 0 Then
                NextHighestPrimeNumber = 1

            Else
                NextHighestPrimeNumber = "Pick A Positive Integer"

            End If

        Exit Function

Else

    'Create Array
    ReDim Prime_Array(0 To 4) As Double
    GoTo StartArrayPopulate
DoneWithStartingArray:

    'zz failed code: If StartingNumber Mod 2 = 0 Then
    If StartingNumber - (Int(StartingNumber / 2) * 2) = 0 Then
        StartingNumber = StartingNumber - 1
    End If

NewNumber:
        StartingNumber = StartingNumber + 2
        CeilingTest = INT(VBA.Sqr(StartingNumber))


    'Array loop
    For i = LBound(Prime_Array) To UBound(Prime_Array)
        If Prime_Array(i) > CeilingTest Then
            NextHighestPrimeNumber = StartingNumber
            Exit Function
        'zz failed code: ElseIf StartingNumber Mod Prime_Array(i) = 0 Then 
GoTo NewNumber
        ElseIf StartingNumber - (Int(StartingNumber / Prime_Array(i)) * Prime_Array(i)) = 0 Then GoTo NewNumber
        End If
    Next i


    'Add new Array Value
ExpandDim:
    ReDim Preserve Prime_Array(UBound(Prime_Array) + 1)
    Prime_Array(UBound(Prime_Array)) = NextHighestPrimeNumber(Prime_Array(UBound(Prime_Array) - 1))

    'test if bigger than ceiling
    If Prime_Array(UBound(Prime_Array)) > CeilingTest Then
        NextHighestPrimeNumber = StartingNumber
        Exit Function

    'zz failed code: ElseIf StartingNumber Mod Prime_Array(UBound(Prime_Array)) = 0 Then GoTo NewNumber
    ElseIf StartingNumber - (Int(StartingNumber / Prime_Array(UBound(Prime_Array))) * Prime_Array(UBound(Prime_Array))) = 0 Then GoTo NewNumber

    Else
        GoTo ExpandDim
    End If

End If


Exit Function

StartArrayPopulate:   
Prime_Array(0) = 3
Prime_Array(1) = 5
Prime_Array(2) = 7
Prime_Array(3) = 11
Prime_Array(4) = 13

GoTo DoneWithStartingArray

End Function

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM