Jump to content

Recommended Posts

Posted

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

Posted

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

Posted

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.

Posted (edited)

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

Posted

@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

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
  • Recently Browsing   0 members

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