1

I just tried three pieces of code:

#include<cstdio>
#include<cmath>
#include<cstring>
int main()
{
    int a = 3;
    int b = pow(10,a);
    printf("%d",b);
    return 0;
}
//Output:1000

#include<cstdio>
#include<cmath>
#include<cstring>
int main()
{
    int a = 3;
    int b = pow(10,a-1);
    printf("%d",b);
    return 0;
}
//Output:99

#include<cstdio>
#include<cmath>
#include<cstring>
int main()
{
    int a = 3;
    int b = pow(10,a-2);
    printf("%d",b);
    return 0;
}
//Output:10

I would like to know why the second block of code will output 99, is it because of floating point precision? Or is it because I should use float numbers in the pow function?(Such as 10.0) I'm usually confused about the accuracy of C++, I will be grateful for your help.

holy Ye
  • 5
  • 6
  • 3
    Long story short: `pow` is not for integer math. – Baum mit Augen Jan 13 '17 at 03:20
  • You *are* using floating point numbers with `pow`, you're just converting them back and forth from integers and back again. – Dietrich Epp Jan 13 '17 at 03:22
  • 1
    It's not the `10` vs `10.0` that's an issue. The problem is the `int b ...` which means any imprecision in the return of `pow(10, 2)` will simply be truncated. So `99.9999999 + some epsilon` will become `99`. (Though I am a little surprised that `pow(10,2)` doesn't return the result `100` precisely. That probably has something to do with the floating point standard.) – Disillusioned Jan 13 '17 at 03:34
  • What OS / compiler are you using? Have you seen the same results on various ones? – Grisha Levit Jan 13 '17 at 03:41
  • [Why pow(10,5) = 9,999 in C++](http://stackoverflow.com/q/9704195/995714), [Strange pow(x, y); behaviour](http://stackoverflow.com/q/14714115/995714) – phuclv Jan 13 '17 at 03:42

2 Answers2

0

Conversion of a floating-point value to an integer is done by truncation — you get the next integer closest to zero. If pow is imprecise and too low, then truncation will exacerbate it.

lround(pow(10,2)) might be more appropriate.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
0

For integer exponents the following template can be very handy:

template <typename T> inline constexpr T pow( T base, int exponent )
{
    return (exponent == 0) ? static_cast<T>(1.0) : ( (exponent>0) ? base*pow(base, exponent-1) : pow( static_cast<T>(1.0)/base, -exponent ) );
}

If you plan to use it with a C++ standard prior C++11, just remove the constexpr keyword.

  • could you explain a bit about what it is doing.. – hg_git Jan 13 '17 at 03:44
  • In C++14 forward, the body can be simply `T ret = 1; for ( exponent -- ) ret *= base; return ret;` – Potatoswatter Jan 13 '17 at 03:49
  • Are you talking about a simple method of exponentiation? How efficient is it? – holy Ye Jan 13 '17 at 05:30
  • The intention is to provide a pow function for every arithmetic type (which could be checked by using std::enable_if. If you plug in a type without operator* it will yield a compiler error in this version). Note that the exponent needs to be integer. As efficiency is concerned: I've never actually tested it. The calculation is performed recursively, why I'd guess it's rather slow, but type safe. The real advantage is the compile time evaluation resulting from the constexpr. If both base and exponent are know at compile time, this call will yield just a constant in the program text. – SimdSeemsSuitable Jan 13 '17 at 07:08
  • Your post doesn't answer the question in any way. He asked *why the second block of code outputs 99*, not *how to implement a `pow` function*. And your implementation is not good either. Real integer `pow` functions use at least [exponentiation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring) for faster calculation – phuclv Feb 25 '17 at 13:09