c++ - 超过 10^10 限制时 pow 函数的精度损失?
问题描述
做我的第一个 uni 作业,并遇到了这个问题:
任务:求所有 n 个元素的总和,其中 n 是数字中数字的个数(n=1,表示 1、2、3...例如 8、9,答案为 45)
问题:我写的代码已经正确地得到了所有测试答案,直到 10 的 9 次方,但是当它达到 10 的 10 次方时,答案开始出错,这真的很接近我应该得到的,但不完全存在(例如,我的输出 = 49499999995499995136,预期结果 = 49499999995500000000)
真的很感激一些帮助/见解,我猜这与变量类型有关,但不太确定可能的解决方案..
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
int main()
{
int n;
double ats = 0, maxi, mini;
cin >> n;
maxi = pow(10, n) - 1;
mini = pow(10, n-1) - 1;
ats = (maxi * (maxi + 1)) / 2 - (mini * (mini + 1)) / 2;
cout << setprecision(0) << fixed << ats;
}
解决方案
我认为您正在将浮点数拉伸到超出其精度的范围。让我解释:
C pow() 函数将双精度数作为参数。您正在传递整数,编译器正在添加代码以在它们到达 pow() 之前将它们转换为双精度数。(无论如何,当您获得返回值时,您将其存储为双精度值,因为您以这种方式声明它)。
正是因为点“浮动”,所以浮点数被称为这种方式。在 double 中,有一个符号位,一些位用于尾数,一些位用于指数。在二进制中,提升到 2 的幂相当于将小数点向右移动(如果提升到负数,则向左移动)。所以基本上指数是用二进制表示小数点在哪里。对双精度数使用这种内存表示的最大优势是,对于接近 0 的数字,您可以获得很多精度,而随着数字变大,精度会逐渐降低。
最后一件事正是发生在你身上的事情。您的号码太大而无法准确存储。所以它被四舍五入到最接近的二的幂之和(二的幂是二进制中右边全为零的数字)。
快速实验:在浏览器中按 F12,打开 javascript 控制台并输入 49499999995499995136。就我而言,在 chrome 中,我重现了同样的问题。
如果你真的真的很想用这么大的数字精确,那么你可以试试这些库中的一些,但这对于学生程序来说太高级了,你不需要它。如果用户输入的数字太大,只需添加一个 if 块并打印一条错误消息(教授们喜欢这个,这实际上是非常正确的)。
推荐阅读
- c++ - 私有成员 c++ 问题
- d3.js - D3.js 遍历嵌套数组找到最大值
- c - 检查认证后在 tuxedo 上使用 libcurl 时停止
- nginx - HMAC对称密钥加密nginx中的标头?
- python - 如何仅在 Python 中将数字除以 10?
- python - Pickle 动态生成具有灵活父类的类?
- javascript - 从 Google 电子表格值创建 HTML 下拉列表
- flutter - 如何将我的颤振应用程序配置为网络
- kubernetes - 在我们已经有 kubernetes 服务的情况下,我们在哪些情况下需要 Kubernetes 中的容器网络?
- javascript - Discord.js 允许命令后面的单词更多