My company has a piece of software, sporting a rather large codebase. Recently I was assigned the task of checking wether the code would compile on an x86_64 target using gcc 4.1.2. I've gotten pretty far in the compilation with very minor modifications to the code but just this morning I got a somewhat confusing compile error.
The code is trying, and failing, to call powfrom <cmath> using int, unsigned int& as parameters. The compiler spits out an error because it can't find a suitable match to call. The overloads for pow in <cmath> are as follows:
double pow(double base, double exponent)
long double pow(long double base, long double exponent)
float pow(float base, float exponent)
double pow(double base, int exponent)
long double pow(long double base, int exponent)
I'm not quite shure as to why this builds on our 32-bit environments but that's beside the point right now.
My question is: how should I cast the parameters, which pow should I use? Thanks.
P.S. I can't change the datatype of the parameters as doing so would require too much work. My assignment is to get the code to compile, detailing any hacks I make so that later, we can go over those hacks and find proper ways do deal with them.
If you are making many calls to pow(int, unsigned int) why don't you just code it by yourself? If execution speed is not an issue, it's not much work.
Otherwise, I'd use a pow() overload whose input parameters are guaranteed to contain your expected values, such as pow(float, float) or pow(double, double). Anyway, I feel that making your own version could prevent problems with conversion between floating point and integer.
The result will always be integer, with these types of arguments.
Depending on the expected range of the arguments, especially the exponent, you should choose for the float or double or long double version.
So that would become
pow( (float) i, (int)ui );
You can find the allowed range of arguments by solving the equation pow(i,ui) < max_double.
Related
I have two values p=19, q=14. I want to calculate pq using the power function pow(p, q).
Here is my code:
long long p=19,q=14;
cout<<pow(p,q);
The correct answer is: 799006685782884121 but my code gives me 799006685782884096 which is incorrect.
I have also tried doing these calculations using unsigned long long instead of long long, but this didn't help.
The pow function is defined as:
double pow(double x, double y);
Which means that it takes floating point arguments and returns a floating point result. Due to the nature of floating point numbers, some numbers can not be exactly represented. The result you're getting is probably the closest match possible.
Note also that you're doing two (probably lossy) conversions:
converting the arguments from long long to double, and
converting the result of the function from double to long long.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n,i,ele;
n=5;
ele=pow(n,2);
printf("%d",ele);
return 0;
}
The output is 24.
I'm using GNU/GCC in Code::Blocks.
What is happening?
I know the pow function returns a double , but 25 fits an int type so why does this code print a 24 instead of a 25? If n=4; n=6; n=3; n=2; the code works, but with the five it doesn't.
Here is what may be happening here. You should be able to confirm this by looking at your compiler's implementation of the pow function:
Assuming you have the correct #include's, (all the previous answers and comments about this are correct -- don't take the #include files for granted), the prototype for the standard pow function is this:
double pow(double, double);
and you're calling pow like this:
pow(5,2);
The pow function goes through an algorithm (probably using logarithms), thus uses floating point functions and values to compute the power value.
The pow function does not go through a naive "multiply the value of x a total of n times", since it has to also compute pow using fractional exponents, and you can't compute fractional powers that way.
So more than likely, the computation of pow using the parameters 5 and 2 resulted in a slight rounding error. When you assigned to an int, you truncated the fractional value, thus yielding 24.
If you are using integers, you might as well write your own "intpow" or similar function that simply multiplies the value the requisite number of times. The benefits of this are:
You won't get into the situation where you may get subtle rounding errors using pow.
Your intpow function will more than likely run faster than an equivalent call to pow.
You want int result from a function meant for doubles.
You should perhaps use
ele=(int)(0.5 + pow(n,2));
/* ^ ^ */
/* casting and rounding */
Floating-point arithmetic is not exact.
Although small values can be added and subtracted exactly, the pow() function normally works by multiplying logarithms, so even if the inputs are both exact, the result is not. Assigning to int always truncates, so if the inexactness is negative, you'll get 24 rather than 25.
The moral of this story is to use integer operations on integers, and be suspicious of <math.h> functions when the actual arguments are to be promoted or truncated. It's unfortunate that GCC doesn't warn unless you add -Wfloat-conversion (it's not in -Wall -Wextra, probably because there are many cases where such conversion is anticipated and wanted).
For integer powers, it's always safer and faster to use multiplication (division if negative) rather than pow() - reserve the latter for where it's needed! Do be aware of the risk of overflow, though.
When you use pow with variables, its result is double. Assigning to an int truncates it.
So you can avoid this error by assigning result of pow to double or float variable.
So basically
It translates to exp(log(x) * y) which will produce a result that isn't precisely the same as x^y - just a near approximation as a floating point value,. So for example 5^2 will become 24.9999996 or 25.00002
When I directly output std::pow(10,2), I get 100 while doing (long)(pow(10,2)) gives 99. Can someone explained this please ?
cout<<pow(10,2)<<endl;
cout<<(long)(pow(10,2))<<endl;
The code is basically this in the main function.
The compiler is mingw32-g++.exe -std=c++11 using CodeBlocks
Windows 8.1 if that helps
Floating point numbers are approximations. Occasionally you get a number that can be exactly represented, but don't count on it. 100 should be representable, but in this case it isn't. Something injected an approximation and ruined it for everybody.
When converting from a floating point type to an integer, the integer cannot hold any fractional values so they are unceremoniously dropped. There is no implicit rounding off, the fraction is discarded. 99.9 converts to 99. 99 with a million 9s after it is 99.
So before converting from a floating point type to an integer, round the number, then convert. Unless discarding the fraction is what you want to do.
cout, and most output routines, politely and silently round floating point values before printing, so if there is a bit of an approximation the user isn't bothered with it.
This inexactness is also why you shouldn't directly compare floating point values. X probably isn't exactly pi, but it might be close enough for your computations, so you perform the comparison with an epsilon, a fudge factor, to tell if you are close enough.
What I find amusing, and burned a lot of time trying to sort out, is would not have even seen this problem if not for using namespace std;.
(long)pow(10,2) provides the expected result of 100. (long)std::pow(10,2) does not. Some difference in the path from 10,2 to 100 taken by pow and std::pow results in slightly different results. By pulling the entire std namespace into their file, OP accidentally shot themselves in the foot.
Why is that?
Up at the top of the file we have using namespace std; this means the compiler is not just considering double pow(double, double) when looking for pow overloads, it can also call std::pow and std::pow is a nifty little template making sure that when called with datatypes other than float and double the right conversions are taking place and everything is the same type.
(long)(pow(10,2))
Does not match
double pow(double, double)
as well as it matches a template instantiation of
double std::pow(int, int)
Which, near as I can tell resolves down to
return pow(double(10), double(2));
after some template voodoo.
What the difference between
pow(double(10), double(2))
and
pow(10, 2)
with an implied conversion from int to double on the call to pow is, I do not know. Call in the language lawyers because it's something subtle.
If this is purely a rounding issue then
auto tempa = std::pow(10, 2);
should be vulnerable because tempa should be exactly what std::pow returns
cout << tempa << endl;
cout << (long) tempa << endl;
and the output should be
100
99
I get
100
100
So immediately casting the return of std::pow(10, 2) into a long is different from storing and then casting. Weird. auto tempa is not exactly what std::pow returns or there is something else going on that is too deep for me.
These are the std::pow overloads:
float pow( float base, float exp );
double pow( double base, double exp );
long double pow( long double base, long double exp );
float pow( float base, int iexp );//(until C++11)
double pow( double base, int iexp );//(until C++11)
long double pow( long double base, int iexp ); //(until C++11)
Promoted pow( Arithmetic1 base, Arithmetic2 exp ); //(since C++11)
But your strange behaviour is MINGW's weirdness about double storage and how the windows run-time doesnt like it. I'm assuming windows is seeing something like 99.9999 and when that is cast to an integral type it takes the floor.
int a = 3/2; // a is = 1
mingw uses the Microsoft C run-time libraries and their implementation of printf does not support the 'long double' type. As a work-around, you could cast to 'double' and pass that to printf instead.
Therefore, you need double double:
On the x86 architecture, most C compilers implement long double as the 80-bit extended precision type supported by x86 hardware (sometimes stored as 12 or 16 bytes to maintain data structure alignment), as specified in the C99 / C11 standards (IEC 60559 floating-point arithmetic (Annex F)). An exception is Microsoft Visual C++ for x86, which makes long double a synonym for double.[2] The Intel C++ compiler on Microsoft Windows supports extended precision, but requires the /Qlong‑double switch for long double to correspond to the hardware's extended precision format.[3]
I am building a C++ program to verify a mathematical conjecture for up to 100 billion iterations. In order to test such high numbers, I cannot use a C++ int, so I am using the NTL library, using the type ZZ as my number type.
My algorithm looks like this:
ZZ generateNthSeq(ZZ n)
{
return floor(n*sqrt(2));
}
I have the two libraries being imported:
#include <cmath>
#include <NTL/ZZ.h>
But obviously this cannot compile because I get the error:
$ g++ deepness*.cpp
deepness.cpp: In function ‘NTL::ZZ generateNthSeq(NTL::ZZ)’:
deepness.cpp:41: error: no matching function for call to ‘floor(NTL::ZZ)’
/usr/include/bits/mathcalls.h:185: note: candidates are: double floor(double)
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/cmath:262: note: long double std::floor(long double)
/usr/lib/gcc/x86_64-redhat-linux/4.4.7/../../../../include/c++/4.4.7/cmath:258: note: float std::floor(float)
Stating that the floor mathematical operation cannot accept a ZZ class type. But I need the numbers to be pretty big. How can I accomplish what I want to do, which is to floor the function, while using the NTL library?
Note that it doesn't really make sense to apply floor to an integral type (well, it does, it's just a no-op). What you should be really worried about is the fact that your code is apparently passing something of type ZZ into floor!
That is, what can n * sqrt(2) possibly mean here?
Also, before even writing that, I'd've checked the documentation to see if integer * floating point actually exists in the library -- usually for that to be useful at all, you need arbitrary precision floating types available.
Checking through the headers, there is only one multiplication operator:
ZZ operator*(const ZZ& a, const ZZ& b);
and there is a conversion constructor:
explicit ZZ(long a); // promotion constructor
I can't figure out how your code is even compiling. Maybe you're using a different version of the library than I'm looking at, and the conversion constructor is implicit, and your double is getting "promoted" to a ZZ. This is surely not what you want, since promoting sqrt(2) to a ZZ is simply going to give you the integer 1.
You either need to:
look into whether or not NTL has arbitrary precision floating point capabilities
switch to a library that does have arbitrary precision floating point capabilities
convert your calculation to pure integer arithmetic
That last one is fairly easy here: you want
return SqrRoot(sqr(n) * 2); // sqr(n) will be a bit more efficient than `n * n`
Why should I get this error
C2668: 'abs' : ambiguous call to overloaded function
For a simple code like this
#include <iostream>
#include <cmath>
int main()
{
unsigned long long int a = 10000000000000;
unsigned long long int b = 20000000000000;
std::cout << std::abs(a-b) << "\n"; // ERROR
return 0;
}
The error still presents after removing std::. However if I use int data type (with smaller values) there is no problem.
The traditional solution is to check that manually
std::cout << (a<b) ? (b-a) : (a-b) << "\n";
Is that the only solution?
The check seem the only really good solution. Alternatives require type bigger than yours and nonstandard extension to use it.
You can go with solutions casting to signed long long if your range fits. I would hardly suggest that way, especially if the implementation is placed in a function that does only that.
You are including <cmath> and thus using the "floating-point abs".
The "integer abs" is declared in <cstdlib>.
However, there is no overload for unsigned long long int (both a and b are, thus a-b is, too), and the overload for long long int only exists since C++11.
First, you need to include the correct header. As pointed out by gx_, <cmath> has a floating-point abs and on my compiler it actually compiles, but the result is probably not the one you expected:
1.84467e+19
Include <cstdlib> instead. Now the error is:
main.cpp:7:30: error: call of overloaded ‘abs(long long unsigned int)’ is ambiguous
main.cpp:7:30: note: candidates are:
/usr/include/stdlib.h:771:12: note: int abs(int)
/usr/include/c++/4.6/cstdlib:139:3: note: long int std::abs(long int)
/usr/include/c++/4.6/cstdlib:173:3: note: long long int __gnu_cxx::abs(long long int)
As you can see, there is no unsigned overload of this function, because computing an absolute value of something which is of type unsigned makes no sense.
I see answers suggesting you to cast an unsigned type to a signed one, but I believe this is dagereous, unless you really know what you are doing!
Let me ask first what is the expected range of the values a and b that you are going to operate on? If both are below 2^63-1 I would strongly suggest to just use long long int. If that is not true however, let me note that your program for the values:
a=0, b=1
and
a=2^64-1, b=0
will produce exactly the same result, because you actually need 65 bits to represent any possible outcome of a difference of 2 64-bit values. If you can confirm that this is not going to be a problem, use the cast as suggested. However, if you don't know, you may need to rethink what you are actually trying to achieve.
Because back before C++ with C you used to have use abs, fabs, labs for each different type, c++ allows overloading of abs, in this case it doesn't understand or isn't happy with your overload.
Use labs(a-b) seeing as you're using longs, this should solve your problem.