### pow()

i have a function that do a calculations and also use `pow()`, BUT, it's really strange that when, for example, i write:

 `` `` ``(int) pow (10.00, 5);``

the result is:
 100000

i.e. one hundred thousand

BUT, when i write:

 `` `` ``(int) pow (10.00, 6);``

the result is:

 1000000

which is 1 MILLION!!

any1 can give an explanation..?

edit:
Last edited on
I don't see anything strange, just basic math. 105 is 1 with 5 zeros (100,000), 106 is 1 with 6 zeros (1,000,000).

What do you expect the output to be?

chipp wrote:
any1 can give an explanation..?

It's a really good compiler ... that does exactly what it's told!
Multiply 100'000 by 10. What do you think that new number will be?

I'll give a hint...it will be 1'000'000. One million.
 really good compiler ... that does exactly what it's told
I was going say that simple correct behavior is a pretty low bar to qualify a compiler as being "really good", but then I remembered that it can even get pow "wrong" sometimes, depending on the implementation of the compile-time vs. run-time pow:
https://stackoverflow.com/questions/17063102/differences-in-rounded-result-when-calling-pow
You have to hand it to pow(), though - it's pretty tight:

 ``123456789`` ``````#include #include using namespace std; int main() { cout << exp( 6 * log( 10.00 ) ) - 1000000 << '\n'; cout << pow( 10.00, 6 ) - 1000000 << '\n'; }``````

 ```1.28057e-09 0```
I still wish it had an int power overload. But it does a really good job on floating point powers for sure.

<cmath> since C++11 allows integral types to be called in pow(). Promoting the integral type to a floating point type for use in pow().
https://en.cppreference.com/w/cpp/numeric/math/pow

I think jonnin's point is that it still inevitably does floating-point arithmetic. It also is not constexpr, but many compilers often have built-in functions that check if the arguments are integral or not, and will optimize calls when appropriate.
Last edited on
it is just sluggish, is my point. x*x is a ton faster than pow(x,2), give it a try :)
yes, I know why. My point is the standard should overload a smart, hot integer powers only version; we did this a couple years back in the forum and just about anything we coded beat pow by a wide margin, whether a straight up loop or using the bits of the exponent.
> x*x is a ton faster than pow(x,2)

Not necessarily; the standard library overload for integral exponents may be smart enough
(particularly when the exponent is 2).
See: https://gcc.godbolt.org/z/vGd54ev89

guys, i really feel very much stupid and feel like an idiot rn... this is probably the most embarrassing thread ever (but, i believe we also learned something even from the most ridiculous things tho)... i feel i just wanna delete this thread fr...

this probably bcoz i was quite sleepy when i write it... and also, probably, bcoz i was too much focus on the number's length...

so my code snippet was like this:
 ``12345678`` ``````std::string num; std::cout << "Enter: "; std::cin >> num; double len = num.size(); if (len == 7) { std::cout << "million" /* bla bla bla */; }``````

i probably was too focus on the length (i.e. 7), so when `pow(10.00, 6)` are the one that resulting 1 million, i thought it was wrong (coz i thought the right code should be `pow(10.00, 7)`)

this is a very embarrassing thread (fr -_-) but, since i believe there's no stupid question, i believe we can also learned many things from this

thx, guys
JLBorges wrote:
the standard library overload for integral exponents may be smart enough

Sorry in advance for being pedantic :+)

Noted that you did say may, but I am wondering if this is an implementation dependent thing, see the code below from compiler explorer using MSVC 19.30.

Edit: I am aware the standard does not specify how things are done, just how they should behave.

I couldn't find much written about it on cppreference, or in the standard. The standard just has the function signature (none of them were `int`), which is probably why cppreference says the integer argument is converted to `double`. I was looking at the draft c++23 standard (N4901), presumably the same as the previous ones in this respect, because this is not a new feature in c++23.

g++ and clang++ produce identical code:

 ``123456`` ``````pow2_mul(double): vmulsd xmm0, xmm0, xmm0 ret pow2_lib(double): vmulsd xmm0, xmm0, xmm0 ret``````

x64 MSVC 19.30
 ``12345678910111213141516171819`` ``````n\$ = 8 double pow2_mul(double) PROC ; pow2_mul movsd QWORD PTR [rsp+8], xmm0 movsd xmm0, QWORD PTR n\$[rsp] mulsd xmm0, QWORD PTR n\$[rsp] ret 0 double pow2_mul(double) ENDP ; pow2_mul n\$ = 48 double pow2_lib(double) PROC ; pow2_lib \$LN3: movsd QWORD PTR [rsp+8], xmm0 sub rsp, 40 ; 00000028H mov edx, 2 movsd xmm0, QWORD PTR n\$[rsp] call double pow(double,int) ; pow add rsp, 40 ; 00000028H ret 0 double pow2_lib(double) ENDP ``````
Last edited on
> I am wondering if this is an implementation dependent thing

Yes, any possible optimisation is up to the implementation.

> which is probably why cppreference says the integer argument is converted to double.

Converted to double for overload (7); not for overloads (4), (5), (6) which accept an exponent of type int
https://en.cppreference.com/w/cpp/numeric/math/pow

JLBorges wrote:
Converted to double for overload (7); not for overloads (4), (5), (6) which accept an exponent of type int

Overloads 4,5,6 are annotated "until c++11" , hopefully most of us are in the category of using something later than c++11 :+) . I have some bias, in that I am always using the latest of compilers and standards, and am always viewing things through that lens. However, I do realise that some are forced to still use old compilers / standards.

Thanks for your always expert advice; with a positive and polite attitude. Cheers :+)
Last edited on
 ``123456789`` ``````#include #include using namespace std; int main() { cout << pow( -10.0, 6.0 ) << '\n'; cout << pow( -10.0, 6.1 ) << '\n'; }`````` ```1e+06 -nan```

pow() seems to be capable of recognising where the exponent is sufficiently close to an integer ... even if that exponent is a double.

Not sure that I'd rely on this behaviour, though.

Fascinating what other languages do:
Fortran:
 ```program test print *, (-10.0) ** 6 ! Legitimate; will be done by repeated-multiply, not exp-log ! print *, (-10.0) ** 6.0 ! Simply won't compile end program test```

Python:
 ```print( (-10.0) ** 6.0 ) # OK, gives 1000000.0 print( (-10.0) ** 6.1 ) # Well, gives the (correct) complex number!```
Last edited on
> Overloads 4,5,6 are annotated "until c++11"

The exponent is a floating point value now; but some library implementations do check if it is an integer.
For instance, GNU libstdc++'s __ieee754_pow has this: ` /* First see whether `y' is a natural number. ... */`
https://github.com/bminor/glibc/blob/92b963699aae2da1e25f47edc7a0408bf3aee4d2/sysdeps/i386/fpu/e_pow.S#L117
Apropos of nothing regarding how pow() overloads work, it is interesting (to me at least) to see there are differences in output using std::format vs. using just std::cout:
 ``1234567891011`` ``````#include #include #include int main() { std::cout << pow(10, 6) << '\t'; std::cout << pow(10, 6.1) << '\n'; std::cout << std::format("{}\t{}\n", pow(10, 6), pow(10, 6.1)); }``````
 ```1e+06 1.25893e+06 1e+06 1258925.411794166```

Change the two format replacement fields so they use a specific number of digits, say `{:.10}`, and the output is as follows:
 ```1e+06 1.25893e+06 1000000 1258925.412```

I keep discovering new things to like about using <format> :)
Last edited on
Topic archived. No new replies allowed.