Menu

Is pow(5,2)=24? Yes for Dev C++

2006-01-20
2012-09-26
1 2 > >> (Page 1 of 2)
  • logicwonder

    logicwonder - 2006-01-20

    consider the code

    include<stdio.h>

    include<math.h>

    int main(void)
    {
    int a=5,b=2,c;
    c=pow(a,b);
    printf("%d",c);
    getch();
    }

    The output of this program when executed in the Bloodshed compiler is 24.

    How does 5 square become 24.

    Many numbers does not give a correct value with pow function.
    eg: 10,20..

    BAD IDE

     
    • Nobody/Anonymous

      Well, really yes for Dev C++

      But the problem is not just in pow(5^2) but for many other nos. I tried 1 to 50 and found almost 40 numbers not giving their squares correctly.

      Well, GCC doen't have that problem. It is the trouble with this implementation.

       
    • Ian Walker

      Ian Walker - 2006-01-20

      The standard pow function casts your ints to floats, computes the answer as a float, then casts it back to an int.

      casting from a float to an int truncates the number, and does not round. Thus what is calculated as 24.999997 becomes 24, no matter how close to 25 it is.

      Three solutions to your problem.

      1) Add 0.5 to the result of the pow function before assigning to integer c. This will ensure correct rounding.

      2) Make c a float

      3) Implement your own sqr function that squares integers. If you only want to work with integers, this will be MUCH faster than all the float conversion that is going on. A basic example would be:

      inline int sqr(int x) {return x*x;}

      Or if you're using C++, you can get all fancy and use an inline template function:

      template <typename T>
      inline T sqr(const T& x) {return x*x;}

      which will work for all the builtin types, and any user types that support operator*

      Hope this helps,

      Ian

       
    • Amanda Wee

      Amanda Wee - 2006-01-20

      pow() returns a double, so this is probably the result of floating point inaccuracy, i.e. a value just below 24 (but very close to 25) was truncated to 24.

      You can avoid this truncation by using the %f format specifier instead, methinks. In any case, the problem is not with the IDE, but with either the code or the compiler. Frankly, floating point truncation is not the fault of the compiler, so I would say that the code simply isnt written the way it should be.

       
    • Amanda Wee

      Amanda Wee - 2006-01-20

      hmm... just had a thought - since the problem lies with the truncation, using %f shouldnt help as the truncation is done before the output.

       
    • Nobody/Anonymous

      the result depends on a good deal more than the ide and the ide not at all. as posted the result on my machines is 25. it has everything to do with how pow and doubles are implemented.

      ian, the standard uses double not float. double on most machines, that i know, can accurately represent integer, not closely but exactly, numbers from 0 to 1e8.

       
      • Ian Walker

        Ian Walker - 2006-01-20

        Sorry, it's an old bad habit of mine to use the word 'float' to mean 'floating point type', ie float, double, long double, or some float-like class.

        double can indeed accurately represent integers, however, there may be a rounding error introduced within the pow function itself.

        Cheers,

        Ian

         
        • Nobody/Anonymous

          "Sorry, it's an old bad habit of mine to use the word 'float' to mean 'floating point type', ie float, double, long double, or some float-like class."

          well that is just confusing.

          "double can indeed accurately represent integers, however, there may be a rounding error introduced within the pow function itself."

          i know hence my how pow is implemented comment. an interesting case the first time i noticed this a negative exponent would introduce errors but a positive one would not.

           
    • Amanda Wee

      Amanda Wee - 2006-01-20

      "double on most machines, that i know, can accurately represent integer, not closely but exactly, numbers from 0 to 1e8."

      I had the impression that double, like float, cannot represent integral values exactly, with the exception of specific integers.

       
      • Nobody/Anonymous

        try this code, but be prepaired to ctrl+c out. then see http://www.gotw.ca/gotw/067.htm for more information.

        include <stdio.h>

        include <math.h>

        include <time.h>

        void d()
        {
        double d = 1e8;
        while(d > 0)
        {
        d--;
        }
        }

        void f()
        {
        float f = 1e8;
        while(f > 0)
        {
        f--;
        }
        }

        int main()
        {
        clock_t td = clock();
        d();
        td = clock() - td;
        clock_t tf = clock();
        f();
        tf = clock() - tf;
        printf("%d - %d", td, tf);
        return(0);
        }

         
    • Anonymous

      Anonymous - 2006-01-20

      If a function returns a floating point value and you assign it to an integer, you get what you deserve.

      As for 'the standard uses double not float. double on most machines, that i know, can accurately represent integer, not closely but exactly' - that is nonsense. What is true however, is that because the output functions (printf and ostream) display values rounded to fewer significant figures that the floating point types hold internally, so the value is rounded to a whole number, for example 24.99999999999999999 would be displayed as 25; but is implicitly (or explictly) cast to an int), it will become 24.

      The solution as Ian has pointed out is to make the types agree correctly, to round rather than truncate:

      c =(int)(pow(a,b) + 0.5) ;

      which Ian also mentioned.

      Clifford

       
      • Nobody/Anonymous

        oh? and you think i am wrong about what exactly?
        before your ignorance gets the better of you why not read the webpage i linked.

         
        • Nobody/Anonymous

          and keep in mind before you accuse me of nonsense that i said most and not all.

           
    • Nobody/Anonymous

      I tried the code logicwonder posted in gcc compiler (Linux), MVC++ , Turbo C, Bloodshed.

      All the programs produced correct outputs except the Bloodshed Dev.

      The above discussion cannot explain this error.

      I think its the problem with beta version.

       
    • Ian Walker

      Ian Walker - 2006-01-20

      From math.h, line 160:

      / 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.
      /

       
      • Nobody/Anonymous

        interesting. float.h has this to add:

        /
        MSVCRT.dll _fpreset initializes the control register to 0x27f,
        the status register to zero and the tag word to 0FFFFh.
        This differs from asm instruction finit/fninit which set control
        word to 0x37f (64 bit mantissa precison rather than 53 bit).
        By default, the mingw version of _fpreset sets fp control as
        per fninit. To use the MSVCRT.dll _fpreset, include CRT_fp8.o when
        building your application.
        /

         
    • Amanda Wee

      Amanda Wee - 2006-01-20

      "The above discussion cannot explain this error."
      It does, at least in the sense that the implementation of pow() is most probably the culprit.

      "I think its the problem with beta version."
      No, the Dev-C++ IDE may be in beta, but the MinGW port of GCC 3.4.2 is stable.

       
    • Nobody/Anonymous

      Dev-C++ is just an IDE, it's not a compiler, it's not a linker, it just provides a fancy text editor that integrates with the MinGW compiler. I notice the person that tried GCC, MVC++, etc. didn't try MinGW outside of Dev.

       
    • Nobody/Anonymous

      perhaps it is more the way mingw interfaces with the msvcrt then the way it is implemented but none the less the code should have used explicit rounding fix the way ian suggested. better safe than sorry.

      clifford you need to not always assume you know more than you do. the ieee 754 standard says that a double precision, 64 bit, float will exactly represent all integers from 0 to 2^53. the only question is whether or not the standard is exactly implemented on a particular platform.

       
      • Anonymous

        Anonymous - 2006-01-21

        I stand corrected. It has a 53bit mantissa, so it can. To the anon I responded to on that point: I retract the 'nonsense' remark. The subsequent example and link however, while interesting do not prove your point (despite the fact you were right), it demonstrates something else altogether.

        In a practical sense however it is nonsense, (the remark was not intended to be personally derogotory), because regardless of what a particular representation is capable of, the library, compiler code generation, and the FPU implementation are beyond your control. Hoping it is all perfect and optimal is a road to failed code.

        There is also more going on that just the representation. The original values have been operated on and converted by code you have no control over. Nothing says that either pow() nor the implicit conversions to and from integers may not introduce imprecision.

        It is not an issue for most people but the assumption of IEEE-754 is platform specific, (although since that is what the FPU implements on x86, that is no doubt what is used). The the C/C++ standards do not require IEEE-754 representation, again a moot point for most possibly, but I don't always code for x86, and the processors I do code for seldom have an FPU, so all bets are off in my world; consequently you code what will always work rather that what should work in a perfect world.

        Clifford

         
    • Nobody/Anonymous

      Intersting. My thought exactly. I compiled with the version of GCC that was in my MinGW installation on this computer, ran it in the MSYS window, and got the right answer.

      I then checked, and found that the version of GCC I was using in MinGW was 3.2, so I updated to 3.4.2.

      Again running in the MSYS window, I get the correct 25.

      Cygwin gave the correct answer as well....

      Still looking....

      Wayne

       
      • Nobody/Anonymous

        it also correctly display 25 for 2.95.3 4.0.2 and 4.2-2006014.

         
        • Nobody/Anonymous

          windows xp sp2 by the way.

           
          • Wayne Keen

            Wayne Keen - 2006-01-20

            Well, that would be more helpful if you would tell us whether that is through MinGW or not...

             
            • Nobody/Anonymous

              i have about forty compilers on my dev computer but i thought considering the discussion that it would be obvious. i was adding it to your discussion that it most likely has nothing to with the compiler, but yes those were mingw.

               
1 2 > >> (Page 1 of 2)

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.