Recently i write a block of code:
const int sections = 10;
for(int t= 0; t < 5; t++){
int i = pow(sections, 5- t -1);
cout << i << endl;
}
And the result is wrong:
9999
1000
99
10
1
If i using just this code:
for(int t = 0; t < 5; t++){
cout << pow(sections,5-t-1) << endl;
}
The problem doesn't occur anymore:
10000
1000
100
10
1
Does anyone give me an explaination? thanks you very much!
What happens is that your answer is actually 99.9999 and not exactly 100. This is because
pow
is double. So, you can fix this by usingi = ceil(pow())
.Your code should be:
From Here
Looking at the
pow()
function:double pow (double base, double exponent);
we know the parameters and return value are alldouble
type. But the variablenum
,i
andres
are allint
type in code above, when tranformingint
todouble
ordouble
toint
, it may cause precision loss. For example (maybe not rigorous), the floating point unit (FPU) calculatepow(10, 4)=9999.99999999
, thenint(9999.9999999)=9999
by type transform in C++.How to solve it?
Solution1
Change the code:
Solution2
Replace floating point unit (FPU) having higher calculation precision in
double
type. For example, we use SSE in Windows CPU. In Code::Block 13.12, we can do this steps to reach the goal: Setting -> Compiler setting -> GNU GCC Compile -> Other options, add-mfpmath=sse -msse3
The picture is as follows:
add <code>-mfpmath=sse -msse3</code> http://aleeee.qiniudn.com/change%20SSE%20in%20CB.png
There must be some broken
pow
function in the global namespace. Thenstd::pow
is "automatically" used instead in your second example because of ADL.Either that or
t
is actually a floating-point quantity in your first example, and you're running into rounding errors.When used with fractional exponents, pow(x,y) is commonly evaluated as
exp(log(x)*y)
; such a formula would mathematically correct if evaluated with infinite precision, but may in practice result in rounding errors. As others have noted, a value of 9999.999999999 when cast to an integer will yield 9999. Some languages and libraries use such a formulation all the time when using an exponentiation operator with a floating-point exponent; others try to identify when the exponent is an integer and use iterated multiplication when appropriate. Looking up documentation for thepow
function, it appears that it's supposed to work whenx
is negative andy
has no fractional part (whenx
is negative and`y
is even, the result should bepow(-x,y)
; wheny
is odd, the result should be-pow(-x,y)
. It would seem logical that wheny
has no fractional part a library which is going to go through the trouble of dealing with a negativex
value should use iterated multiplication, but I don't know of any spec dictating that it must.In any case, if you are trying to raise an integer to a power, it is almost certainly best to use integer maths for the computation or, if the integer to be raised is a constant or will always be small, simply use a lookup table (raising numbers from 0 to 15 by any power that would fit in a 64-bit integer would require only a 4,096-item table).
Due to the representation of floating point values
pow(10.0, 5)
could be 9999.9999999 or something like this. When you assign that to an integer that got truncated.EDIT: In case of
cout << pow(10.0, 5);
it looks like the output is rounded, but I don't have any supporting document right now confirming that.EDIT 2: The comment made by BoBTFish and this question confirms that when
pow(10.0, 5)
is used directly incout
that is getting rounded.Whats happens is the pow function returns a double so when you do this
the decimal .99999 cuts of and you get 9999.
while printing directly or comparing it with 10000 is not a problem because it is runded of in a sense.