On 2018-09-07 17:03 +0200, Marc Glisse wrote: > On Sat, 8 Sep 2018, sisyphus1@xxxxxxxxxxxxxxx wrote: > > > Hi, > > > > The demo program: > > > > /****/ > > /* try.c */ > > #include <stdio.h> > > #include <math.h> > > > > int main(void) { > > > > int x = -1074; > > > > printf("%e\n", pow (2.0, (double)x)); > > printf("%e\n", pow (2.0, x)); > > > > return 0; > > } > > > > /****/ > > > > If I build that program (using g++ version 7.3.0) with "g++ -ansi -o try > > try.c" I get output of: > > > > 4.940656e-324 > > 0.000000e+000 > > > > whereas I expected output to be: > > > > 4.940656e-324 > > 4.940656e-324 > > > > I guess that means that either my expectation is buggy, or something else is > > buggy. The "buggy" thing is <https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Other-Builtins.html>: Built-in Function: double __builtin_powi (double, int) Returns the first argument raised to the power of the second. Unlike the pow function no guarantees about precision and rounding are made. GCC's <cmath> header do different thing for C++11 and C++03. In C++03, `double std::pow(double, int)` is implemented by `__builtin_powi`. In C++11, it is implemented by casting the second parameter to double, and then call `pow(double, double)` from libc. The C++11 behavior is defined by 26.8 [c.math] para 11: > Moreover, there shall be additional overloads sufficient to ensure: > 1. If any argument corresponding to a double parameter has type long > double, then all arguments corresponding to double parameters are > effectively cast to long double. > 2. Otherwise, if any argument corresponding to a double parameter has > type double or an integer type, then all arguments corresponding to > double parameters are effectively cast to double. > 3. Otherwise, all arguments corresponding to double parameters are > effectively cast to float. And libstdc++ is doing right thing (casting the `int` parameter to `double`). But C++03 is not so clear and does not define what should libstdc++ do. Libstdc++ chooses to call __builtin_powi. Unfortunately it is not so precise. > > Note 1: > > If the "-ansi" switch is omitted, then the output matches my expectation. "-ansi" means "-std=c++98". Now GCC is defaulted to C++14. > Don't use -ansi, use -std= . Most likely you did not mean to use > -std=c++98. > > The exact set of overloads of pow in the C++ standard has varied with > time, https://en.cppreference.com/w/cpp/numeric/math/pow gives some idea. > > > Note 2: > > If cmath is #included instead of math.h, then the output matches my > > expectation. > > If you include cmath and not math.h, you should use std::pow. Yes. std::pow gives the same "buggy" output. But, I wonder why don't we change the C++98/03 `pow` behavior to be same as C++11? This is still standard and is more precise. Jonathan how do you think? -- Xi Ruoyao <xry111@xxxxxxxxxxxxxxxx> School of Aerospace Science and Technology, Xidian University