Question

#include <iostream>
#include <cmath>

using namespace std;

unsigned long long modExp(unsigned long long b, unsigned long long e, unsigned long long m)
{
    unsigned long long remainder;
    unsigned long long x = 1;

    while (e != 0)
    {
        remainder = e % 2;
        e= e/2;

        // These lines
        if(remainder==1)
            x=(unsigned long long)fmodl(((long double)x*(long double)b),(long double)m);
        b=(unsigned long long)fmodl(((long double)b*(long double)b),(long double)m);
    }
    return x;
}

int main()
{
    unsigned long long lastTen = 0,netSum=0;
    unsigned long long sec(unsigned long long,unsigned long long);

    for(int i=1;i<1001;i++)
    {
        lastTen = modExp(i,i,10000000000);
        netSum += lastTen;
        netSum %= 10000000000;
        cout << lastTen << endl ;
    }

    cout << netSum%10000000000 << endl;
    cout << sizeof(long double) << endl;
    return 0;
}

This is my program to compute the last ten digits of a sum of series. It uses Arithmetic Exponentiation technique to compute the last 10 digits. It works well for 10^9. But when I go for a 10^10 it collapses.

So in order to use the higher size data types I have converted the number to be multiplied to long double and multiplied them(which would again yield long double) so if we take modulus on this number we would get the answer correctly. But I did not get the right answer again it causes the same wrong answer.

My thought to make such thing is like this

  • an unsigned long long is 8 bytes, since I am moding i would get a large number as a 10 digit number so multiplying 2, ten digit numbers would not fit in unsigned long long so it would cycle in unsigned long long
  • so for the above point I convert the unsigned long long to long double(which is 12 bytes) and since it has large space it is large enough to fit a 20 digit product of 2 ten digit numbers

Can any one say what is the flaw in this logic??

Was it helpful?

Solution

The common long double implementation cannot represent all 20-digit decimal numbers exactly.

The characteristics of long double are not completely determined by the C++ standard, and you do not state what implementation you are using.

One common implementation of long double uses a 64-bit significand. Although it may be stored in twelve bytes, it uses only ten, and 16 of those are used for the sign and exponent, leaving 64 for the significand (including an explicit leading bit).

A 64-bit significand can represent integers without error up to 264, which is about 1.845•1019. Thus, it cannot represent all 20-digit numbers exactly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top