0
#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;
}

这是我计算系列和的最后十位数字的程序。它使用算术指数技术来计算最后 10 位数字。它适用于 10^9。但是当我选择 10^10 时,它就会崩溃。

因此,为了使用更大尺寸的数据类型,我已将要相乘的数字转换为 long double 并将它们相乘(这将再次产生 long double),因此如果我们对该数字取模,我们将正确得到答案。但是我没有再次得到正确的答案,它导致了同样的错误答案。

我做这样的事情的想法是这样的

  • unsigned long long 是 8 个字节,因为我正在修改,所以我会得到一个大数字作为 10 位数字,所以乘以 2,10 位数字不适合 unsigned long long 所以它会在 unsigned long long 中循环
  • 所以对于以上几点,我将 unsigned long long 转换为 long double(即 12 个字节),并且由于它有很大的空间,它足够大,可以容纳 2 个 10 位数字的 20 位乘积

谁能说出这个逻辑的缺陷是什么?

4

1 回答 1

2

常见的long double实现不能准确地表示所有 20 位十进制数。

的特性long double并不完全由 C++ 标准决定,您也没有说明您使用的是什么实现。

一种常见的实现long double使用 64 位有效位。虽然它可以存储在 12 个字节中,但它只使用 10 个字节,其中 16 个用于符号和指数,剩下 64 个用于有效位(包括显式的前导位)。

一个 64 位的有效数可以无错误地表示整数,最高可达 2 64,大约为 1.845•10 19。因此,它不能准确地表示所有 20 位数字。

于 2013-08-30T13:32:39.097 回答