in reply to Re^3: Q: NaN again
in thread Q: NaN again

web # perl -e '$a="nan"; print sprintf("%.2f",$a)' nan web # perl -v This is perl, v5.8.8 built for x86_64-linux ----- For Win32: This is perl, v5.8.4 built for MSWin32-x86-multi-thread perl -e "$a='nan'; print sprintf('%.2f',$a)" 0.00

Replies are listed 'Best First'.
Re^5: Q: NaN again
by syphilis (Archbishop) on Oct 19, 2006 at 13:31 UTC
    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