Problems with NaN (not a number)

Thanks Syed.
Let’s wait for any clarification from Xojo’s behalf.

To recap, this is the function I recommend:

Function IsTrueNumeric (value As String) As Boolean
  static rx as RegEx
  if rx is nil then
    rx = new RegEx
    rx.SearchPattern = "(?i)\\A[\\d\\-+e\\.]+\\z"
  end if
  return rx.Search( value ) <> nil and IsNumeric( value )
End Function

Str without a format string does at the very lowest level use an OS supplied routine for turning the value into a string

Thanks Kem and Norman,

But the truth is the deeper I go in this subject the weirder it is.
I’ve just tried this code:

dim a as double = sqrt(-1) dim at1 as string = format (a, "-0.00e") dim at2 as string = str(a) Dim b as Boolean = IsNumeric(a) Dim c as Boolean = IsNumeric(at1) Dim d as Boolean = IsNumeric(at2)

I get this:

So it seems that IsNumeric detects non numbers when stringed but not when in numerical format.
May be I can use this, but I’d like to know what happens in OSX and Linux.
Can anyone check it?
TIA

On OS X:

FYI, this returns True:

  dim e as Boolean = IsNumeric( "NAN" )

The code below results in the listed values on SuSE SLES 11 Linux in Xojo2014R1.1.

[code]
Dim a As Double = Sqrt(-1)
Dim at1 As String = Format (a, “-0.00e”)
Dim at2 As String = Str(a)
Dim b As Boolean = IsNumeric(a)
Dim c As Boolean = IsNumeric(at1)
Dim d As Boolean = IsNumeric(at2)

a NaN.
at1 NAN.00
at2 NaN
b True
c False
d True[/code]

Thanks Kem and Syed,

With your information I have enough to understand the problem.
I definitely will ask for a feature to do have such a function in Xojo.
Meanwhile I’ll do something myself.

Is there a way to create a NaN constant?

I recently ran into some OS X routines which expect CGRectNull constant, which is not a Nil pointer but rather a CGRect that is filled with {NaN,NaN,NaN,NaN}. I know MBS has a function to make it, but I was curious how to create that in pure Xojo code.

NaN is a particular 8-byte representation of a Double. Use an 8-byte memoryblock, set the appropriate byte values, and pull the DoubleValue out of it. (Or use 4 bytes and SingleValue if it expects a 4-byte representation.)

NaN can be several different representations
https://en.wikipedia.org/wiki/NaN

Interesting : this page https://docs.oracle.com/cd/E19957-01/806-3568/ncg_math.html gives the hex values, and for a Single it looks like it’s 7fc00000, for a double it’s 7ff80000 00000000.

Does Ctype work here? Can one say
dim s as single = Ctype(“NaN”) ?

From what I’ve found CGRectNull is [Inf, Inf, 0, 0].

You can use CGRectIntersection with 2 disjoint rects and that’s what I get back.

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

There can be MANY different NaN’s :slight_smile:

[quote=226772:@Norman Palardy]NaN can be several different representations
https://en.wikipedia.org/wiki/NaN[/quote]

Very nice.

[quote=226774:@Will Shank]From what I’ve found CGRectNull is [Inf, Inf, 0, 0].
You can use CGRectIntersection with 2 disjoint rects and that’s what I get back.[/quote]

Here’s what I’ve found:

  const CGPoint CGPointZero = {0,0};
  const CGSize CGSizeZero = {0,0};
  const CGRect CGRectZero = {{0,0},{0,0}};
  const CGRect CGRectNull = {{NAN,NAN},{NAN,NAN}};
  const CGRect CGRectInfinite = {{INFINITY,INFINITY},{INFINITY,INFINITY}};

[quote=226777:@Michael Diehr]Here’s what I’ve found:

const CGRect CGRectNull = {{NAN,NAN},{NAN,NAN}};[/quote]
Did you try CGRectIntersection? The docs say it returns CGRectNull and when I stringify such a result I get Inf, Inf, 0, 0

INF can be made like this, for Single

m = new MemoryBlock(4) m.UInt32Value(0) = &h7F800000 v = m.SingleValue(0)
for Double

m = new MemoryBlock(8) m.UInt64Value(0) = &h7FF0000000000000 v = m.DoubleValue(0)
but also v = 1 / 0 works. So this should make a CGRectNull in both 32 and 64 bit.

dim r As CGRect r.x = 1 / 0 r.y = 1 / 0 r.w = 0 r.h = 0

Will, it seems you may be correct?

  dim r as CGRectMBS = CGRectMBS.Null
  dim mb as MemoryBlock = r.Binary
  break

In the debugger, mb has the bytes

0000 807F 0000 807F 0000 0000 0000 0000

I wonder if this is a documentation bug or something else? Perhaps the OS just looks at the 2 first Singles and if they are Inf it doesn’t matter what the last two are?

I couldn’t find a definition in Apples docs or Xcode and turned to tweets like this
https://twitter.com/MSch/status/271528930035507201
Docs like this define a CGRectNull with NaNs but it’s the Free Software Foundation, Inc. not Apple
http://svn.gna.org/svn/gnustep/libs/opal/trunk/Source/OpalGraphics/CGGeometry.m

Also it seems only one of x y needs to be INF to be considered a CGRectNull…

[code] dim r As CGRect
r.x = 9
r.y = 1 / 0
r.w = 6
r.h = 2

declare function CGRectIsNull lib “Cocoa” (r As CGRect) As Boolean

MsgBox "null " + Str(CGRectIsNull(r)) //True[/code]