#1275 pow() error only on Win

WSL
closed
later
Known_Feature
2013-02-06
2009-03-22
Clausfor
No

Values produced are different if compiled under Windows (wrong results) or under Linux (correct results).

#include <stdio.h>
#include <math.h>
int main()
{
int x;
x=5;
printf ("%d\n" , (int)pow(x,2)); /* gives 24 !!! */
printf ("%d\n" , (int)pow(5,2)); /* gives 25 */
printf ("%f\n" , pow(x,2)); /* gives 25.000000 */
printf ("%f\n" , pow(5,2)); /* gives 25.000000 */
x=pow(x,2);
printf ("%d\n" , x); /* gives 24 */
return 0;
}

#define __MINGW32_VERSION 3.14
#define __W32API_VERSION 3.11

ld -v
GNU ld (GNU Binutils) 2.18.50.20080109

gcc -v
Reading specs from ./../lib/gcc/mingw32/3.4.5/specs
Configured with: ../gcc-3.4.5/configure --with-gcc --with-gnu-ld --with-gnu-as -
-host=mingw32 --target=mingw32 --prefix=/mingw --enable-threads --disable-nls --
enable-languages=c,c++,f77,ada,objc,java --disable-win32-registry --disable-shar
ed --enable-sjlj-exceptions --enable-libgcj --disable-java-awt --without-x --ena
ble-java-gc=boehm --disable-libgcj-debug --enable-interpreter --enable-hash-sync
hronization --enable-libstdcxx-debug
Thread model: win32
gcc version 3.4.5 (mingw-vista special)

Discussion

  • Clausfor

    Clausfor - 2009-03-23

    math.h says (but why on Linux it works?):
    /* Excess precision when using a 64-bit mantissa for FPU math ops can
    cause unexpected results with some of the MSVCRT math functions. For
    example, unless the function return value is stored (truncating to
    53-bit mantissa), calls to pow with both x and y as integral values
    sometimes produce a non-integral result.
    One workaround is to reset the FPU env to 53-bit mantissa
    by a call to fesetenv (FE_PC53_ENV). Amother is to force storage
    of the return value of individual math functions using wrappers.
    NB, using these wrappers will disable builtin math functions and
    hence disable the folding of function results at compile time when
    arguments are constant. */

     
  • Keith Marshall

    Keith Marshall - 2009-03-25
    • labels: 844818 --> mingw runtime (deprecated use WSL)
    • milestone: --> Known_Feature
     
  • Keith Marshall

    Keith Marshall - 2009-03-25

    This is indeed an excess precision issue. Note that the comment says that this can lead to unexpected results with some of the *MSVCRT* math functions; GNU/Linux doesn't use MSVCRT, so why would you expect that comment to apply?

    I'm not sure if this is something we should "fix". Users need to be aware of the potential pitfalls with *any* floating point math implementation, and be prepared to deal with them; possible solutions to this particular issue are identified in the comment, for example:

    $ cat pow-test.c

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

    double my_pow( double base, double exp )
    {
    /* Wrapper forces intermediate store of result */

    return base = pow( base, exp );
    }

    int main()
    {
    int x = 5;
    double xx;

    /* Excess precision may lead to rounding error */

    printf( "%d\n", (int)(pow( x, 2 )) );

    /* Forcing an intermediate store circumvents this... */

    printf( "%d\n", (int)(xx = pow( x, 2 )) );

    /* ...as does redirecting the function call to the wrapper */

    # define pow my_pow

    printf( "%d\n", (int)(pow( x, 2 )) );

    return 0;
    }

    $ gcc pow-test.c

    $ ./a
    24
    25
    25

     
  • Earnie Boyd

    Earnie Boyd - 2013-02-06
    • labels: mingw runtime (deprecated use WSL) --> msvcrt, pow
    • status: open --> closed
    • assigned_to: Earnie Boyd
    • resolution: --> later
    • category: --> Known_Feature
    • milestone: Known_Feature --> WSL