Search code examples
vb6naninfinity

How do you get VB6 to initialize doubles with +infinity, -infinity and NaN?


VB6 doesn't appear to make it that easy to store +infinity, -infinity and NaN into double vars. It would help if it could so that I could do comparisons with those values in the context of complex numbers. How?


Solution

  • A few different things. As you can see from Pax's example, you really just need to look up the IEEE 754 standard and then plug your bytes into the right places. The only caution I would give you is that MicroSoft has deprecated RtlMoveMemory due to it's potential for creating security issues of the overflow type. As an alternative you can accomplish this in "pure" VB with a little careful coercion using User Defined Types and LSet. (Also note that there are two types of NaN.)

    Option Explicit
    
    Public Enum abIEEE754SpecialValues
        abInfinityPos
        abInfinityNeg
        abNaNQuiet
        abNaNSignalling
        abDoubleMax
        abDoubleMin
    End Enum
    
    Private Type TypedDouble
        value As Double
    End Type
    
    Private Type ByteDouble
        value(7) As Byte
    End Type
    
    Public Sub Example()
        MsgBox GetIEEE754SpecialValue(abDoubleMax)
    End Sub
    
    Public Function GetIEEE754SpecialValue(ByVal value As abIEEE754SpecialValues) As Double
        Dim dblRtnVal As Double
        Select Case value
        Case abIEEE754SpecialValues.abInfinityPos
            dblRtnVal = BuildDouble(byt6:=240, byt7:=127)
        Case abIEEE754SpecialValues.abInfinityNeg
            dblRtnVal = BuildDouble(byt6:=240, byt7:=255)
        Case abIEEE754SpecialValues.abNaNQuiet
            dblRtnVal = BuildDouble(byt6:=255, byt7:=255)
        Case abIEEE754SpecialValues.abNaNSignalling
            dblRtnVal = BuildDouble(byt6:=248, byt7:=255)
        Case abIEEE754SpecialValues.abDoubleMax
            dblRtnVal = BuildDouble(255, 255, 255, 255, 255, 255, 239, 127)
        Case abIEEE754SpecialValues.abDoubleMin
            dblRtnVal = BuildDouble(255, 255, 255, 255, 255, 255, 239, 255)
        End Select
        GetIEEE754SpecialValue = dblRtnVal
    End Function
    
    Public Function BuildDouble( _
        Optional byt0 As Byte = 0, _
        Optional byt1 As Byte = 0, _
        Optional byt2 As Byte = 0, _
        Optional byt3 As Byte = 0, _
        Optional byt4 As Byte = 0, _
        Optional byt5 As Byte = 0, _
        Optional byt6 As Byte = 0, _
        Optional byt7 As Byte = 0 _
        ) As Double
        Dim bdTmp As ByteDouble, tdRtnVal As TypedDouble
        bdTmp.value(0) = byt0
        bdTmp.value(1) = byt1
        bdTmp.value(2) = byt2
        bdTmp.value(3) = byt3
        bdTmp.value(4) = byt4
        bdTmp.value(5) = byt5
        bdTmp.value(6) = byt6
        bdTmp.value(7) = byt7
        LSet tdRtnVal = bdTmp
        BuildDouble = tdRtnVal.value
    End Function
    

    One last side note, you can also get NaN this way:

    Public Function GetNaN() As Double
        On Error Resume Next
        GetNaN = 0 / 0
    End Function