5

I need to use pow in my c++ program and if i call the pow() function this way:

long long test = pow(7, e);

Where

e is an integer value with the value of 23.

I always get 821077879 as a result. If i calculate it with the windows calculator i get 27368747340080916343.. Whats wrong here? ):

I tried to cast to different types but nothing helped here... What could be the reason for this? How i can use pow() correctly?

Thanks!

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
user1004012
  • 87
  • 2
  • 8
  • 2
    Doesn't `pow` return a `long double` not a `long long`? – Eric Petroelje Nov 17 '11 at 21:58
  • 1
    With long double i get 821077879.00000000 as a result which is still wrong.. – user1004012 Nov 17 '11 at 22:00
  • 1
    @EricPetroelje `pow()` returns a `double`, which is converted to `long long` upon assignment to `test`. The overflow in the conversion is undefined behavior (some platforms have a hardware exception for this overflow). – Pascal Cuoq Nov 17 '11 at 22:01

3 Answers3

8

The result is doesn't fit in long long.

If you want to deal with very big numbers then use a library like GMP

Or store it as a floating point (which won't be as precise).

Applying modulo:

const unsigned int b = 5; // base
const unsigned int e = 27; // exponent
const unsigned int m = 7; // modulo

unsigned int r = 1; // remainder

for (int i = 0; i < e; ++i)
  r = (r * b) % m;

// r is now (pow(5,27) % 7)
Pubby
  • 51,882
  • 13
  • 139
  • 180
  • Is there another way for just this one case? I don't want to implement a whole library in my program for one specific line of code.. – user1004012 Nov 17 '11 at 22:04
  • @user1004012 Store it as a floating point `long double` instead of an integer. – Pubby Nov 17 '11 at 22:05
  • As written above, i get the same result: "With long double i get 821077879.00000000 as a result which is still wrong.." What's wrong? – user1004012 Nov 17 '11 at 22:09
  • that's working correctly, thank you. but if i want to apply the modulo operation to the double value the next problem appears.. how to calculate modulo on such a big value? – user1004012 Nov 17 '11 at 22:15
  • @user1004012 You can't on floating points. What exactly is your problem? It may be doable if you post your entire problem instead of what you think is the problem. – Pubby Nov 17 '11 at 22:18
  • @user1004012 I've posted how you can find the modulo. – Pubby Nov 17 '11 at 22:31
  • http://en.wikipedia.org/wiki/RSA_%28algorithm%29 i try to implement this.. everything is working except the encryption line were it says: c = m^e (mod n).. this line i want to implement correctly in an c++ apllication. – user1004012 Nov 17 '11 at 22:36
  • oh, haven't seen your response as i posted the last message.. will try this, thanks! – user1004012 Nov 17 '11 at 22:39
6

723 is too big to fit into a long long (assuming it's 64 bits). The value is getting truncated.

Edit: Oh, why didn't you say that you wanted pow(b, e) % m instead of just pow(b, e)? That makes things a whole lot simpler, because you don't need bigints after all. Just do all your arithmetic mod m. Pubby's solution works, but here's a faster one (O(log e) instead of O(e)).

unsigned int powmod(unsigned int b, unsigned int e, unsigned int m)
{
   assert(m != 0);

   if (e == 0)
   {
      return 1;
   }
   else if (e % 2 == 0)
   {
      unsigned int squareRoot = powmod(b, e / 2, m);
      return (squareRoot * squareRoot) % m;
   }
   else
   {
      return (powmod(b, e - 1, m) * b) % m;
   }
}
dan04
  • 87,747
  • 23
  • 163
  • 198
  • So which kind of type should i use then? I wanted to implement this in my rsa function.. – user1004012 Nov 17 '11 at 21:59
  • 1
    ... and the Windows Calculator handles it because from some version onwards they plugged in an arbitrary-precision library to handle the math. – Matteo Italia Nov 17 '11 at 22:00
4

See it live: https://ideone.com/YsG7V

#include<iostream>
#include<cmath>
int main()
{
    long double ldbl = pow(7, 23);
         double dbl  = pow(7, 23);
    std::cout << ldbl << ", " << dbl << std::endl;
}

Output: 2.73687e+19, 2.73687e+19

sehe
  • 374,641
  • 47
  • 450
  • 633