B4J Code Snippet [B4X]Using Infinity and NaN as special Numbers

@wonder posted https://www.b4x.com/android/forum/threads/return-nan-and-infinity.106046/post-663817

This is an addendum to his posting to show how these two objects are both numbers and not numbers, and how to test for that.
B4X:
Private Sub specialNumbers
 
    'Infinity behaves in the expected way as as an infinitely large number
    Dim infinity As Double = 1 / 0
    Log(infinity = -Logarithm(0, cE))        'True
    Log((infinity = infinity))                      'True
    Log((infinity = -infinity))                    'False
    Log(TAB)

    Log((infinity + 5))                       'Infinity
    Log((infinity - 5))                        'Infinity
    Log((infinity * 5))                        'Infinity
    Log((infinity / 5))                        'Infinity
    Log((infinity / 0))                        'Infinity
    Log(infinity * infinity)                 'Infinity
    Log(Sqrt(infinity))                       'Infinity
    Log(Power(cE, infinity))              'Infinity
 
    'Numberformat shows a nice infinity symbol
    Log(NumberFormat2(infinity, 1, 0, 0, False))    '∞
 

    Log((1 / infinity))                        '0
    Log((100 / infinity))                    '0
    Log((1000 / infinity))                   '0
    Log((1000 / -infinity))                 '-0
    Log(TAB)
 
    'However, like the Sqrt(-1), the following are undefined and therefore NaN
    Log((infinity / infinity))         'NaN
    Log((infinity / -infinity))        'NaN

    'The simplest NaN is 0 / 0
    Dim NaN As Double = 0 / 0
    Log((NaN = Sqrt(-1000)))        'False    - this is unexpected, but understandable given that the comparison of NaN with anything return False
    Log((NaN = NaN))                   'False
    Log((NaN = -NaN))                  'False
    Log((NaN = "NaN"))                 'False - this is unexpected, but understandable given the order of the string conversion
    Log(("NaN" = NaN))                 'True

    'IsNumber only checks if string can be converted to number, so it's argument is first converted to a string "NaN"
    '                                        which is (paradoxically) interpreted as a valid a number
    Log(IsNumber(Sqrt(-1)))            'True
    Log(IsNumber(0 / 0))                 'True
    Log(IsNumber(0))                      'True
    Log(IsNumber(infinity))             'True

    'NaN is the only "number" that is not equal to itself - this can be used to test for NaN - see
        'Private Sub IsNaN(z As Double) As Boolean
        '    Return z <> z
        'End Sub
 
    Log(IsNaN(Sqrt(-1)))            'True
    Log(IsNaN(0 / 0))                 'True
    Log(IsNaN(0))                       'False
    Log(IsNaN(infinity))              'False
    Log(IsNaN(NaN))                  'True
 
    'all computations with NaN result in NaN          [NaN could be used as "missing" value in Statistics]
    Log((NaN + 5))                   'NaN
    Log((NaN - 5))                    'NaN
    Log((NaN * 5))                    'NaN
    Log((NaN / 5))                    'NaN
    Log((NaN / 0))                    'NaN
    Log(NaN * NaN)                 'NaN
    Log(Sqrt(NaN))                   'NaN
    Log(Power(cE, NaN))          'NaN
    Log((1 / NaN))                    'NaN
    Log((100 / NaN))                'NaN
    Log((1000 / NaN))              'NaN
    Log((NaN / NaN))              'NaN
End Sub

Private Sub IsNaN(z As Double) As Boolean
    Return z <> z
End Sub

Private Sub NotNaN(z As Double) As Boolean
    Return z = z
End Sub
 
Last edited:

William Lancee

Well-Known Member
Licensed User
One important fact to know!

Integers and Longs do not respond to NaN in the way that floats or doubles do

B4X:
    'The Integer type converts "NaN" into 0;  Float and Double convert it to NaN
    Dim anInteger As Int = "NaN"             'unlike all other strings this one does not a throw an error, which can lead to hard to find bugs
    Dim aFloat As Float = "NaN"
    Dim aDouble As Double = "NaN"
    Log(anInteger & TAB & aFloat & TAB & aDouble)
    'Log: 0    NaN    NaN

    'The following shows how NaN can be used with floats and doubles
    Dim vector As String = $"1, 3, 6, spoiled, 1, ?, 7, 10, 9, , 2, 3"$            'three missing/invalid values
    Dim sum As Int = 0
    Dim num As Int = 0
    Dim v() As String = Regex.Split(",", vector)
    Log(v.Length)
    For Each s As String In v
        If IsNumber(s) = False Then s = "NaN"                'converts "spoiled", "?" and "" to NaN
        Dim a As Float = s           'if this is an Integer or Long, the final answer will be wrong!
        If a = a Then                     'only summed if not NaN => (NaN is NOT equal to itself)
            Log(a)
            sum = sum + a
            num = num + 1
        End If
    Next
    Log(sum & TAB & num & TAB & (sum /num) & TAB & "adjusted sum = " & (v.Length * sum / num))

    'Log: 42    9    4.666666666666667    adjusted sum = 56
 
Last edited:
Top