使用c ++的非常大的数字总和

Lov*_*ing -2 c++

我试图解决这个特殊问题:项目欧拉#16:

2 ^ 15 = 32768,其数字之和为3 + 2 + 7 + 6 + 8 = 26.
数字2 ^ 1000的数字之和是多少?

#include <iostream>
#include <cmath>
using namespace std;

int main()
{
   int num;
   cin >> num;
   long double n = pow(2, num);
   cout << fixed << n << endl;
   int sum = 0;
   while(n != 0.0)
   {
      sum = sum + fmod(n, 10);
      n = floor(n/10);
   }
   cout << sum << endl;
}
Run Code Online (Sandbox Code Playgroud)

用户输入为1000时的输出为:

1181
Run Code Online (Sandbox Code Playgroud)

然而,互联网提到了正确的答案,1366而不是1181我得到的.

And*_*ing 5

问题在于第一次计算:

long double n = pow(2, num);
Run Code Online (Sandbox Code Playgroud)

因为即使常规double类型(max :)1.79769e+308也会保持2^1000 = 1.07151e+301没有任何问题,特别是这是一个基数2计算.

请注意,您使用的double版本pow(),fmod()并且floor()代替的long double版本powl(),fmodl()floorl().但这就是我说的不是问题而且不会改变任何东西.

但是while循环中的计算将缺乏精度和舍入误差.进一步使用它们进行算术时,永远不要检查(un)相等的浮点数,请参见SO(网络上有很多关于该主题的讨论和线索).

简而言之:
我认为你的fmod()并且floor()会导致精确丢失和舍入错误.


这是一个工作解决方案(参见ideone),用于将case转换double为a std::string并迭代字符串的每个字符,并将char转换为整数.

简而言之:
它只是使用初始计算(只是double)并将其转换为字符串.

#include <iostream>
#include <cmath>

int main ()
{
   int num;
   std::cin >> num;
   double n = pow(2, num); /* note I use just double */

   std::string nstr = std::to_string(n);
   const char* nstr_p = nstr.c_str();

   std::cout << std::fixed << nstr << std::endl;
   int sum = 0;
   while (std::isdigit(*nstr_p)) /* number contains dot and fractional (.0000) */
   {
      sum = sum + (*nstr_p - '0'); /* convert character to integer and sum it */
      nstr_p++;
   }
   std::cout << sum << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

输出:

1366
Run Code Online (Sandbox Code Playgroud)

请注意,转换:(*nstr_p - '0')假设编码类似于ASCII或其他数字在其十六进制表示中没有间隙的情况下递增.