Yep - it's broken on Win32, and the nature of the breakage varies, depending upon which compiler (ie Visual Studio or MinGW) was used to build perl. I submitted a perlbug report about this (assigned a ticket number of 38779) a while back.
But the example that you've provided fails in the same way, irrespective of whether perl was compiled with Visual Studio 6.0 or MinGW.
I thought this had been fixed with Visual Studio 7.0 but I still I get (on my perl built with Visual Studio 7.0):
F:\>perl -we "$a='nan'; print sprintf('%.2f',$a)"
0.00
Let's face it ... handling of NaN's on Win32 is unreliable. I don't know how you can disable it. You could try re-compiling perl 5.8.8 with the following patch supplied by Jan Dubois in response to my perlbug report.
--- pp.c.orig Wed Mar 22 19:35:45 2006
+++ pp.c Wed Mar 22 21:43:04 2006
@@ -1732,8 +1732,15 @@
}
#endif
{
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+ dPOPTOPnnrl;
+ if (Perl_isnan(left) || Perl_isnan(right))
+ RETSETNO;
+ SETs(boolSV(left < right));
+#else
dPOPnv;
SETs(boolSV(TOPn < value));
+#endif
RETURN;
}
}
@@ -1808,8 +1815,15 @@
}
#endif
{
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+ dPOPTOPnnrl;
+ if (Perl_isnan(left) || Perl_isnan(right))
+ RETSETNO;
+ SETs(boolSV(left > right));
+#else
dPOPnv;
SETs(boolSV(TOPn > value));
+#endif
RETURN;
}
}
@@ -1884,8 +1898,15 @@
}
#endif
{
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+ dPOPTOPnnrl;
+ if (Perl_isnan(left) || Perl_isnan(right))
+ RETSETNO;
+ SETs(boolSV(left <= right));
+#else
dPOPnv;
SETs(boolSV(TOPn <= value));
+#endif
RETURN;
}
}
@@ -1960,8 +1981,15 @@
}
#endif
{
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+ dPOPTOPnnrl;
+ if (Perl_isnan(left) || Perl_isnan(right))
+ RETSETNO;
+ SETs(boolSV(left >= right));
+#else
dPOPnv;
SETs(boolSV(TOPn >= value));
+#endif
RETURN;
}
}
@@ -2029,8 +2057,15 @@
}
#endif
{
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+ dPOPTOPnnrl;
+ if (Perl_isnan(left) || Perl_isnan(right))
+ RETSETYES;
+ SETs(boolSV(left != right));
+#else
dPOPnv;
SETs(boolSV(TOPn != value));
+#endif
RETURN;
}
}
--- pp_hot.c.orig Wed Mar 22 19:35:45 2006
+++ pp_hot.c Wed Mar 22 21:42:38 2006
@@ -306,8 +306,15 @@
}
#endif
{
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+ dPOPTOPnnrl;
+ if (Perl_isnan(left) || Perl_isnan(right))
+ RETSETNO;
+ SETs(boolSV(left == right));
+#else
dPOPnv;
SETs(boolSV(TOPn == value));
+#endif
RETURN;
}
}
--- sv.c.orig Wed Mar 22 21:47:13 2006
+++ sv.c Wed Mar 22 21:31:27 2006
@@ -2134,6 +2134,13 @@
certainly cast into the IV range at IV_MAX, whereas the correc
+t
answer is the UV IV_MAX +1. Hence < ensures that dodgy boundar
+y
cases go to UV */
+#if defined(NAN_COMPARE_BROKEN) && defined(Perl_isnan)
+ if (Perl_isnan(SvNVX(sv))) {
+ SvUV_set(sv, 0);
+ SvIsUV_on(sv);
+ }
+ else
+#endif
if (SvNVX(sv) < (NV)IV_MAX + 0.5) {
SvIV_set(sv, I_V(SvNVX(sv)));
if (SvNVX(sv) == (NV) SvIVX(sv)
--- win32/win32.h.orig Wed Mar 22 19:35:49 2006
+++ win32/win32.h Wed Mar 22 21:35:54 2006
@@ -210,6 +210,11 @@
#define isnan _isnan
+#if _MSC_VER < 1300
+/* VC6 has broken NaN semantics: NaN == NaN returns true instead of f
+alse */
+#define NAN_COMPARE_BROKEN 1
+#endif
+
#endif /* _MSC_VER */
#ifdef __MINGW32__ /* Minimal Gnu-Win32 */
I don't know if it will help. Good luck.
Cheers, Rob |