我试图解决这个特殊问题:项目欧拉#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时的输出为:
Run Code Online (Sandbox Code Playgroud)1181
然而,互联网提到了正确的答案,1366而不是1181我得到的.
问题不在于第一次计算:
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)
输出:
Run Code Online (Sandbox Code Playgroud)1366
请注意,转换:(*nstr_p - '0')假设编码类似于ASCII或其他数字在其十六进制表示中没有间隙的情况下递增.