Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Compare to -NaN

179 views
Skip to first unread message

Alexandru

unread,
May 16, 2018, 5:26:46 AM5/16/18
to
I can't compare a value which is -NaN to -NaN

so if

set x -NaN
expr ($x eq -NaN)

I get

can't use non-numeric floating-point value as operand of "-"

How can I find out, if x is -NaN?

Wright now I'm using "catch" to solve the issue but this is not cool...

Arjen Markus

unread,
May 16, 2018, 5:36:46 AM5/16/18
to
There is no numerical value -NaN - only NaN. Infinity can be positive and negative and even zero can be positive and negative, but "not-a-number" does not have a sign. To complicate things: NaN can be quiet or signalling, but that is a very different matter.

In what context does "-NaN" arise?

Regards,

Arjen

Alexandru

unread,
May 16, 2018, 5:39:07 AM5/16/18
to
I will ttry to provide an example in a few hours. The variable is the result of some mathematic operations.

Rich

unread,
May 16, 2018, 7:01:27 AM5/16/18
to
Alexandru <alexandr...@meshparts.de> wrote:
> I can't compare a value which is -NaN to -NaN

Consider the meaning of NaN.

Not a Number

If something is "Not a Number" how should a /numeric/ comparison work
(remember, the input is "Not a Number"?


If you need to detect that NaN has occurred in a computation, you might
have better success with string comparison against the string NaN:

expr {$variable eq "NaN"}

Alexandru

unread,
May 16, 2018, 7:40:47 AM5/16/18
to
Rich, this what I'm doing already, see my example in the original post. The issue is that I have -NaN, which is not normal. I have to dig further to see ahy I get a minus in the first place.

Alexandru

unread,
May 16, 2018, 8:07:29 AM5/16/18
to
Am Mittwoch, 16. Mai 2018 11:39:07 UTC+2 schrieb Alexandru:
> I will ttry to provide an example in a few hours. The variable is the result of some mathematic operations.

Now I can show where exactly the error is produced. I have C function that I call from within Tcl. The function computes the distance between a point an line in 3D.
The problem is that the function gets the line direction as a zero vector which obviously is wrong, but the problem remains, that C returns -NaN in this case:

static int
DistPoint2Line_Cmd (ClientData cdata, Tcl_Interp *ip, int objc, Tcl_Obj *const objv[]) {
// objv[1] point
// objv[2] point on line
// objv[3] direction of line

Tcl_Obj *obj, *listElemPtr;
double a[3], b[3], c[3], d;
int i;

// Transfer Tcl list C array
for (i=0; i< 3; i++) {
// Get pointer to index value of first vector
Tcl_ListObjIndex(ip, objv[1], i, &listElemPtr);
// Extract the double value from it.
Tcl_GetDoubleFromObj(ip,listElemPtr,&a[i]);

// Get pointer to index value of second vector
Tcl_ListObjIndex(ip, objv[2], i, &listElemPtr);
// Extract the double value from it.
Tcl_GetDoubleFromObj(ip,listElemPtr,&b[i]);

// Get pointer to index value of third vector
Tcl_ListObjIndex(ip, objv[3], i, &listElemPtr);
// Extract the double value from it.
Tcl_GetDoubleFromObj(ip,listElemPtr,&c[i]);
}

d = DistPoint2Line(a,b,c);
obj = Tcl_NewDoubleObj(d);
Tcl_SetObjResult(ip, obj);

return TCL_OK;
}
double DistPoint2Line(double p[3], double a[3], double u[3]) {
double area, x[3];
VectorsSum(a,u,x);
area = TriangleArea(p,a,x);
return (area/VectorNorm(u));
}

The function computes with this input (point, point on line, line direction:
DistPoint2Line {7 0 0} {7 0.0 0} {0 0 0}
the result -NaN

The fuctions computes the result as return (area/VectorNorm(u)); where both division arguments are zero. Somehow interprets the Tcl/C API this result as -NaN. Why? No idea.

Rich

unread,
May 16, 2018, 8:28:30 AM5/16/18
to
Alexandru <alexandr...@meshparts.de> wrote:
> Am Mittwoch, 16. Mai 2018 13:01:27 UTC+2 schrieb Rich:
>> Alexandru <alexandr...@meshparts.de> wrote:
>> > I can't compare a value which is -NaN to -NaN
>>
>> Consider the meaning of NaN.
>>
>> Not a Number
>>
>> If something is "Not a Number" how should a /numeric/ comparison work
>> (remember, the input is "Not a Number"?
>>
>>
>> If you need to detect that NaN has occurred in a computation, you might
>> have better success with string comparison against the string NaN:
>>
>> expr {$variable eq "NaN"}
>
> Rich, this what I'm doing already, see my example in the original
> post.

Actually, your origional contains a syntax error.

You have: expr ($x eq -NaN)

When you should have: expr {$x eq "-NaN"}

The double quotes are critical in 'expr's mini language to distinquish
actual string things that expr should treat as opaque from stuff that
expr should interpret. You also really should replace the parens there
with curly brackets. Your code will be faster and less likely to have
code injection attacks present.

> The issue is that I have -NaN, which is not normal.

Correct, but that was not a topic of your origional posting. That
posting was "how do I *compare* something to "-NaN".

> I have to dig further to see ahy I get a minus in the first place.

Correct, but even if you find that source, you'll still be left with
"compare" to NaN. For which you likely need string compare, for which
the double quotes are required inside "expr".

Alexandru

unread,
May 16, 2018, 8:38:31 AM5/16/18
to
Thanks for the tips, I always use curly brackets, this was just for the sake of faster writing. Originally I tried this:
expr ($x eq {-NaN})
Which issued
extra characters after close-brace
And never thought that placing the curly brackets around the whole expression will solve the problem.
So the solution is
expr {$x eq {-NaN}}

Still intresting is that I get -NaN as a result to the division 0/0 in C.

Many thanks for the help.

Arjen Markus

unread,
May 16, 2018, 9:14:08 AM5/16/18
to
On Wednesday, May 16, 2018 at 2:38:31 PM UTC+2, Alexandru wrote:
> Am Mittwoch, 16. Mai 2018 14:28:30 UTC+2 schrieb Rich:
> > Alexandru wrote:
> > > Am Mittwoch, 16. Mai 2018 13:01:27 UTC+2 schrieb Rich:
I must admit I have never seen that (or my memory is faulty) and I have seen plenty of occurrences of NaN.

It is definitely intriguing - no time at the moment to explore this further, but I will keep it in mind.

Regards,

Arjen

Zoltan Kocsi

unread,
May 16, 2018, 10:37:41 AM5/16/18
to
On Wed, 16 May 2018 05:38:29 -0700 (PDT)
Alexandru <alexandr...@meshparts.de> wrote:

> [...]
> Still intresting is that I get -NaN as a result to the division 0/0
> in C.

Most computers use the IEEE-754 float format.
Without a lot of details, such a number consists of a signum bit, E
exponent bits and M manissa bits. If all bits of the exponent are set
but all bits of the mantissa are 0, that is infinity and the signum bit
indicates its sign. When all the exponent bits are 1 but not all the
mantissa bits are 0, then you have a NaN (and some of the bits in the
mantissa may give you some additional info). For a NaN the meaning of
the signum bit is not defined and it can be in either state.

If it happens to be set and the print routine you use examines the
signum bit first, then you will get a "-" printed before the rest
realises that you have a NaN. Nevertheless, a NaN is a NaN.

By the way, IEEE comparison is a tricky business. For example,
-0 equals +0, which you would expect. You would also expect that +inf
does not equal to any finite number or -inf. It is a bit more
surprising that +inf equals to +inf. Why is it surprising? Because inf
is used to indicate overflow and two wrongs should not make a right, if
you get my drift. Nevertheless, the standard specifies that infinities
with the same sign compare equal.

However, and this is actually important in your case, the standard also
specifies that if an operand of a comparison is NaN, then the
comparison must evaluate false, except if it is for "not equal" in
which case it must return true. Try this:

#include <stdio.h>
#include <math.h>

int main( void )
{
double a = nan(); // Std. math function, returning a NaN
printf( "%f %d\n", a, a == a );
return 0;
}

or, if you prefer Tcl, this:

set a NaN
puts "$a [expr { $a == $a }]"

Lo and behold, a is not equal to itself.

So comparing the return value against NaN does *not* tell you whether
the returned value is NaN or not.

Now, in C there's a handy function, isnan(x) which, as its name
implies, tells you whether x is NaN. Alas, this doesn't exist in Tcl
(at least I couldn't find it) and if you pass a NaN to anything in
expr, it will complain.

In fact, if you pass it -NaN it will spit the dummy, as that parses to
unitary minus operator followed by NaN and expr refuses to evaluate any
operator other than a comparison one on a NaN.

But this is Tcl, everything is a string, so string compare should work,
right? Indeed,

if { [string equal $x "NaN"] || [string equal $x "-NaN"] } {}

does indeed work.

Note, however, that

if { "$x" == "NaN" || "$x" == "-NaN" } {}

does *not* work! Whether 'x' is converted to string to be compared
against the string "NaN" or the string "NaN" is converted to double to
be compared against the value of 'x' is up to the interpreter. You must
use a solution which forces the double to be converted to its string
representation and performs string comparison.

Regards,

Zoltan
--
Zoltán Kócsi
Bendor Research Pty. Ltd.

Alexandru

unread,
May 16, 2018, 10:47:28 AM5/16/18
to
Wow! Impressive answer! Thanks. Very helpfull.
Regards
Alexandru

Arjen Markus

unread,
May 17, 2018, 5:54:03 AM5/17/18
to
Adding a function like that should not be too hard. It might be useful to add similar ones like "is infinite" or "is normal". I feel a TIP coming up :).

Regards,

Arjen

Arjen Markus

unread,
May 17, 2018, 9:28:37 AM5/17/18
to
On Thursday, May 17, 2018 at 11:54:03 AM UTC+2, Arjen Markus wrote:

> Adding a function like that should not be too hard. It might be useful to add similar ones like "is infinite" or "is normal". I feel a TIP coming up :).
>
> Regards,
>
> Arjen

That said, the "canonical" way of checking if a value is NaN, is:

if { $x != $x } {
puts "x is NaN of any sort"
}

as NaNs are by definition unequal to anything even themselves.

Regards,

Arjen

heinrichmartin

unread,
May 17, 2018, 9:52:54 AM5/17/18
to
On Thursday, May 17, 2018 at 3:28:37 PM UTC+2, Arjen Markus wrote:
> if { $x != $x } {
> puts "x is NaN of any sort"
> }

At least for Tcl 8.6.4, x actually can become -NaN, too.
Back to the initial question: replacing bare -NaN with a "constant" [set -NaN -NaN] removes the syntax error, but yields the "wrong" result.

Expr's parser is not word-oriented and processes unary operator - instead of a single token -NaN ...

sled...@gmail.com

unread,
May 17, 2018, 12:42:05 PM5/17/18
to
Hey, I am still working on "what is the square root of -1". NaN is way over my head.

Cecil Westerhof

unread,
May 17, 2018, 1:44:06 PM5/17/18
to
sled...@gmail.com writes:

> On Wednesday, May 16, 2018 at 2:26:46 AM UTC-7, Alexandru wrote:
> Hey, I am still working on "what is the square root of -1".

i or -i.

--
Cecil Westerhof
Senior Software Engineer
LinkedIn: http://www.linkedin.com/in/cecilwesterhof

sled...@gmail.com

unread,
May 17, 2018, 7:37:29 PM5/17/18
to
Exactly!

tombert

unread,
May 22, 2018, 9:10:42 AM5/22/18
to
I ran into similar troubles, then did the following:

proc isreal {value} {
if {[string match -nocase $value "NaN"]} {return 0}
return [string is double -strict $value]
}


Still I wonder why [string is double -strict] does return true on NaN, since this renders the whole [string is double -strict] completely useless to me.

heinrichmartin

unread,
May 22, 2018, 9:40:19 AM5/22/18
to
On Tuesday, May 22, 2018 at 3:10:42 PM UTC+2, tombert wrote:
> Still I wonder why [string is double -strict] does return true on NaN, since this renders the whole [string is double -strict] completely useless to me.

"If -strict is specified, then an empty string returns 0, otherwise an empty string will return 1 on any class."

Even without -strict, my first thought was "what a bug!"; but then [string is] refers to representation. And NaN has a representation as double as Zoltan explained.

Donal K. Fellows

unread,
May 22, 2018, 9:53:21 AM5/22/18
to
On 22/05/2018 14:10, tombert wrote:
> Still I wonder why [string is double -strict] does return true on NaN, since this renders the whole [string is double -strict] completely useless to me.

You can use it with [binary format].

% binary scan [binary format d NaN] cu8 x
1
% set x
0 0 0 0 0 0 248 127

Donal.
--
Donal Fellows — Tcl user, Tcl maintainer, TIP editor.

Uwe Klein

unread,
Jul 6, 2018, 6:28:04 PM7/6/18
to
Am 16.05.2018 um 13:01 schrieb Rich:
> Alexandru <alexandr...@meshparts.de> wrote:
>> I can't compare a value which is -NaN to -NaN
>
> Consider the meaning of NaN.
>
> Not a Number
>
> If something is "Not a Number" how should a /numeric/ comparison work
> (remember, the input is "Not a Number"?
>
% set x NaN
NaN
% expr ($x eq NaN)
1
% expr (abc eq abc)
invalid bareword "abc"

expr apparently knows about NaNs
uwe


Donald Arseneau

unread,
Jul 10, 2018, 3:15:26 AM7/10/18
to
It does know, but no number is equal to NaN, not even NaN itself,
so your example returning "1" threw me for a loop, until I noticed
"eq" rather than "==". That example is weird! It does string
comparison, but the NaN *bare* *string* slips past the defenses
by looking like a potential number.

That's possibly a bug, but it applies to string comparisons on
ordinary numeric strings as well: expr (1.0 eq 1.00)

--
Donald Arseneau as...@triumf.ca
0 new messages