Jump to content

Checking for undefined result from some math functions.


Bowmore
 Share

Recommended Posts

I was wondering if there was a alternative to having to convert the result to a string and cpmparing it to "-1.#IND".

;~ $Probability = 0.99
;~ $Probability = 0.99999999999999999
$Probability = 0
$Tails = 2
$result = inverseNormal($Probability, $Tails)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $result = ' & $result & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    select
        case $result = 0
            ; do something
            ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $result = ' & $result & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
        case string($result) = "-1.#IND" ;<======= Is there a better method to check for undefined
            ; do something
            ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $result = ' & $result & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
        case Else
            ; do somthing else
            ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $result = ' & $result & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    EndSelect

Func inverseNormal($p, $Tails = 1)

    ;'  Adapted for Microsoft Visual Basic from Peter Acklam's
    ;'  "An algorithm for computing the inverse normal cumulative distribution function"
    ;'  (http://home.online.no/~pjacklam/notes/invnorm/)
    ;'  by John Herrero (3-Jan-03)

    ;'Define coefficients in rational approximations
    Const $a1 = -39.6968302866538
    Const $A2 = 220.946098424521
    Const $a3 = -275.928510446969
    Const $a4 = 138.357751867269
    Const $a5 = -30.6647980661472
    Const $a6 = 2.50662827745924

    Const $b1 = -54.4760987982241
    Const $b2 = 161.585836858041
    Const $b3 = -155.698979859887
    Const $b4 = 66.8013118877197
    Const $b5 = -13.2806815528857

    Const $c1 = -7.78489400243029E-03
    Const $c2 = -0.322396458041136
    Const $c3 = -2.40075827716184
    Const $c4 = -2.54973253934373
    Const $c5 = 4.37466414146497
    Const $c6 = 2.93816398269878

    Const $d1 = 7.78469570904146E-03
    Const $d2 = 0.32246712907004
    Const $d3 = 2.445134137143
    Const $d4 = 3.75440866190742

    ;'Define break-points
    Const $p_low = 0.02425
    Const $p_high = 1 - $p_low

    ;'Define work variables
    Local $q, $r, $Z

    ;'If argument out of bounds, raise error
    If $p <= 0 Or $p >= 1 Then SetError(5)

    If $Tails <> 1 Then
        If $p > 0.5 Then
            $p += ((1 - $p) * 0.5)
        Else
            $p *= 0.5
        EndIf
    EndIf


    If $p < $p_low Then
        ;          'Rational approximation for lower region
        $q = Sqrt(-2 * Log($p))

        $Z = ((((($c1 * $q + $c2) * $q + $c3) * $q + $c4) * $q + $c5) * $q + $c6) / (((($d1 * $q + $d2) * $q + $d3) * $q + $d4) * $q + 1)
    ElseIf $p <= $p_high Then
        ;  '    Rational approximation for lower region
        $q = $p - 0.5
        $r = $q * $q
        $Z = ((((($a1 * $r + $A2) * $r + $a3) * $r + $a4) * $r + $a5) * $r + $a6) * $q / ((((($b1 * $r + $b2) * $r + $b3) * $r + $b4) * $r + $b5) * $r + 1)
    ElseIf $p < 1 Then
        ;  '    Rational approximation for upper region
        $q = Sqrt(-2 * Log(1 - $p))
        $Z = -((((($c1 * $q + $c2) * $q + $c3) * $q + $c4) * $q + $c5) * $q + $c6) / (((($d1 * $q + $d2) * $q + $d3) * $q + $d4) * $q + 1)
    EndIf

    Return Round($Z, 4)

EndFunc   ;==>inverseNormal

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Link to comment
Share on other sites

It seems you are getting a not a number value

use the if statement with a double equal sign

if $result == "-1.#IND" Then

ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $result = NaN ' & $result & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console

EndIf

Think you could also get -1.#INF

http://en.wikipedia.org/wiki/NaN

http://www.johndcook.com/IEEE_exceptions_in_cpp.html

not sure why the double equal sign in a case statement is not working

Link to comment
Share on other sites

The alternative is to compare to something that gets the same result. The following two functions aren't really necessary but you get the idea:

Func IsInd($n)
    Return Abs($n) = ASin(2)
EndFunc   ;==>isind

Func IsInf($n)
    Return Abs($n) = (1 / 0)
EndFunc   ;==>isinf

Or you could define two globals:

Global Const $IND = ASin(2)
Global Const $INF = 1 / 0

And then just replace any of your strings with those. Just remember that even IEEE special values are still signed, so there is plus/minus infinity and plus/minus ind (hence the Abs() in the functions above).

This method is far better than comparing to a string. It's future proof, and won't evaluate true for any functions that could return 1.#INF as a valid string.

Link to comment
Share on other sites

Thanks for the responses guys. I like your idea Mat. Although what I had worked fine it just did not feel right. Your suggestion leads me to a much neater solution. What I can do is create Global Consts and then check against them.

For example:

Global Const $__INF = Log(0)
Global Const $__IND = Sqrt(-1)

$result = Log($n)
;............
If $result == $__INF Then
; do something
else $result == $__INF Then
  ;do somethig different
else
  ; do something else
endif

Edit: Revised the example to something that actually works. Looks like I still need to use == to force a string comparison to get it to work but it looks neater.

Edited by Bowmore

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Link to comment
Share on other sites

@Mat

Your method works fine for #INF but not for #IND which for some reason needs to be compared as a string

$Result = Sqrt(-1)

MsgBox(0, $Result, $Result = $Result)
MsgBox(0, $Result, $Result == $Result)

MsgBox(0, Sqrt(-1), Sqrt(-1) = Sqrt(-1))
MsgBox(0, Sqrt(-1), Sqrt(-1) == Sqrt(-1))

"Programming today is a race between software engineers striving to build bigger and better idiot-proof programs, and the universe trying to build bigger and better idiots. So far, the universe is winning."- Rick Cook

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...