Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Working with NAN
#1
My memory is sharp but short. Where a same number is divided by itself the resultant is 1 ( ie 1/1 , 2/2 etc) in keeping with this I'm trying to catch a NAN result and convert it to the value of 1. So NAN doesn't seem to be a numeric nor a string. Is there a way to trap NAN and force a value of 1 ??

Code: (Select All)
a = 0
b = 0
Print
Print
Print " Where a = 0 and b = 0"
Print " a/b = "; a / b
Print " b/a = "; b / a
Result$ = Str$(a / b)

If a / b = nan Or b / a = nan Then
    a = 1
    b = 1
    Print "New Value of a/b = "; a / b
End If

If Result$ = "NAN" Or Result$ = "nan" Then
    a = 1
    b = 1
    Print "New Value of a/b = "; a / b
End If
Reply
#2
An easy way to test for NaN is to compare the result against itself - NaN is the only floating-point value which is not equal to itself. That said, arguably the better way to handle this is to check for the NaN-causing situations before doing the math.
Reply
#3
Pure Basic has a NAN "function". The trick is to find an especially-encoded 32-bit or 64-bit floating-point value to represent NAN. Find two others to represent positive and negative infinity. Maybe another one to represent the square root of -1. And so on.

FROM:
https://en.wikipedia.org/wiki/NaN#Floating_point

Quote:IEEE 754 NaNs are encoded with the exponent field filled with ones (like infinity values), and some non-zero number in the significand field (to make them distinct from infinity values); this allows the definition of multiple distinct NaN values, depending on which bits are set in the significand field, but also on the value of the leading sign bit (but applications are not required to provide distinct semantics for those distinct NaN values).

For example, an IEEE 754 single precision (32-bit) NaN would be encoded as
s111 1111 1xxx xxxx xxxx xxxx xxxx xxxx

where s is the sign (most often ignored in applications) and the x sequence represents a non-zero number (the value zero encodes infinities). In practice, the most significant bit from x is used to determine the type of NaN: "quiet NaN" or "signaling NaN" (see details in Encoding). The remaining bits encode a payload (most often ignored in applications).
Reply
#4
Would this be a success trap for NAN. I'm not sure if the IF statement is proving the NONE existence of a valid number (ie testing for NAN) or no matter what the value of a/b they will simply be forced to their new values of 1/1. I'm looking for this algorythm to only trigger if a/b = NAN.

Code: (Select All)
a = 0
b = 0
If a / b Then
    Print "Value of a/b is "; a / b
    a = 1
    b = 1
    Print "New Value of a/b is "; a / b
End If
Reply
#5
Must do things this way instead as DSMan195276 said:

Code: (Select All)
dim as double a, b
a = 0
b = 0
print DivCheckZero(a, b)
end

function DivCheckZero# (a as double, b as double)
    dim fret as double
    if int(b * 1e+6) = 0 then
        fret = 1
    else
        fret = a / b
    end if
    DivCheckZero# = fret
end function

Might have to make the factor even larger to cover more decimal places for double-precision floating point.

It's not as elegant as "a / b" but there is no helping it if "b" is zero or very darned close to zero.



Could go further in another application:

Code: (Select All)
function newtan# (degrees as double)
    dim fret as double, intd as long
    intd = int(degrees)
    if intd = 90 or intd = 270 then
        fret = 0
    else
        fret = tan(_d2r(degrees))
    end if
    newtan = fret
end function

function newsqrt# (num as double)
    dim fret as double, intd as long
    intd = int(num)
    if intd < 0 then
        fret = 0
    else
        fret = sqr(num)
    end if
    newsqrt = fret
end function

'CHANGED: real, imag
sub altsqrt (num as double, real as double, imag as double)
    dim fret as double, intd as long
    intd = int(num)
    if intd < 0 then
        imag = sqr(num * (-1))
        real = 0
    else
        real = sqr(num)
        imag = 0
    end if
end function

The "altsqrt()" isn't a very good example. Instead it should be able to come up with something like "2 + 3i" with "real" being 2 and "imag" being 3.
Reply
#6
(09-08-2023, 06:06 PM)Dimster Wrote: Would this be a success trap for NAN. ...
That won't work because NaN is "falsey", in an expression like that it turns into a false value. You could use this with `Int()` to turn NaN into zero and do some comparisons, but it would get pretty messy.

Not to repeat myself, but you can do it like this, it looks silly but it does work Tongue

```
a = 0
b = 0
ret = a / b

If ret <> ret Then
    ' NaN is the only value that does not equal itself
    ret = 1
End If

Print ret
```
Reply
#7
Thank you very much mnrvo & DS. Great ideas here to work with. 

It's hard to believe a math formula could actually come up with a None Number value (Not a Number). I guess it all boils down to if zero is a numeric value or a place holder for a void in the infinite number set. 

Logically speaking division by zero shouldn't be infinity either. If zero is a void in the infinite number set (which a NaN result implies), then when we divide 3 apples among 0 people the resultant should be 3, not infinity. 

I understand the history of math credits the Indians with the introduction of zero as a number (and introduced negative numbers) but before that zero was a void. So if zero is not a void and is a real number, then NaN should not exist. End of my rant on NaN.
Reply
#8
(09-09-2023, 01:42 PM)Dimster Wrote: Thank you very much mnrvo & DS. Great ideas here to work with. 

It's hard to believe a math formula could actually come up with a None Number value (Not a Number). I guess it all boils down to if zero is a numeric value or a place holder for a void in the infinite number set. 

Logically speaking division by zero shouldn't be infinity either. If zero is a void in the infinite number set (which a NaN result implies), then when we divide 3 apples among 0 people the resultant should be 3, not infinity. 

I understand the history of math credits the Indians with the introduction of zero as a number (and introduced negative numbers) but before that zero was a void. So if zero is not a void and is a real number, then NaN should not exist. End of my rant on NaN.

I might be misunderstanding you, but I would note that NaN is not infinity or negative infinity, those both have separate floating point values. NaN simply means that there is no answer to what you're trying to do (Ex. distribute 3 apples among 0 people). There are other ways to get NaN, such as taking the square root of a negative, they're all actions that don't result in an answer.

I would also consider that if you allow division by zero to equal anything you break math Tongue Consider this:

Code: (Select All)
c=a/b
a=c*b ' Multiplication and division should be inverses of each-other, so this is always true

' So, if the answer c is supposed to =a when b=0 as you're proposing, then we have a problem
' It implies all numbers equal 0
c=a/0 ' Dividing a by zero. Should equal a, so we'll write that
a=c*0
a=0 ' c*0 is clearly zero.

Ex.
3=3/0 ' a=3, c=3
3=3*0 ' a=c*0
3=0 ' Err...

' Some equations also now have multiple solutions since a/0 and a/1 are the same. Consider:
a=a/x ' What is x? is it both 0 and 1?
a=a*x ' Do the same inverse as before
a*1=a*0 ' a/x and a*x both equal a
1=0 ' Divide off the a
You can also consider the more numeric reasoning. I think we both agree that division by numbers less than zero result in a number larger than a, such as `a/.5=2a`. The smaller and smaller the divisor gets, the closer to infinity it gets. It also can't just be infinity because on the negative side it will approach -infinity, so hence why it just gets a NaN. If you just pick that `a/0=a` then the results would weirdly snap back to `a` after approaching both infinities
Reply
#9
Hi DS
I do follow your math and I do understand the points you are making but... in terms of an AI program, where logic is a key element, NaN screws it all up. In my apple math of 3 apples divided by zero, I didn't mean that math to equal NaN but rather equal infinity. So I do understand that if you divide the 3 apples with the numeric value of zero it goes into it an infinite number of times. I can write code which makes sure my math formulas do not divide by zero, so in effect controlling infinity. But NaN is a different story.

You would think it should also be a simple matter of making sure both my numerator and denominator can not be zero at the same time but as you point out, this is not the only condition which leads to a NaN result. 

Thanks for the discussion, eases the frustration and gets the thinking cap back on.
Reply
#10
Save as isnan.h:

Code: (Select All)
#include <stdio.h>
#include <math.h>
#include <float.h>

int IsNan (long double n);
IsNan (long double n) {
    return -isnan(n);
    }
And then run the following:

Code: (Select All)
DECLARE CUSTOMTYPE LIBRARY "isnan"
    FUNCTION IsNan% (n AS DOUBLE)
END DECLARE

PRINT IsNan(1 / 0)
PRINT IsNan(2 / 3)

And now you can test for Nan, if you decide to.

(There's also isinf which you'd basically implement the same way if you needed it, which tells you if a value is INF or not.  If you need it as well, and can't sort it out on your own, I'll happily toss it into a simple header file for you.)
Reply




Users browsing this thread: 6 Guest(s)