如何解决当超过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;
}
解决方法
出现问题的主要原因是pow()函数。它使用double而不是int。准确性的损失是代表大量数字的代价。 解决问题的方法有3种:
- 对于小n,您可以创建自己的
long long int pow(int x,int pow)
函数。但是有一个问题,就是我们甚至可能long long int
溢出
- 使用长算术函数,如@rustyx所说。您可以使用vector编写自己的代码,或者查找并包含库。
- 有针对主题任务的数学解决方案。它解决了大数字问题。
你可以这样写你的公式
((10 ^ n)-1)*(10 ^ n)-(10 ^ m-1)*(10 ^ m))/ 2,(这里m = n-1)
然后将分子相乘。重新组合它们。提取公倍数10 ^(n-1)。然后您可以看到,该答案具有以下结构:
X9...9Y0...0
表示足够大的n,其中字母X和Y为常数。 因此,您无需计算就可以打印答案“字符串”。
我认为您正在扩展浮点数,超出其精度。让我解释一下:
C pow()函数将double用作参数。您传递的是整数,编译器正在添加代码,以在它们达到pow()之前将其转换为double。 (而且无论如何,因为这样声明,当您获得返回值时,您会将其存储为double)。
之所以这样称呼浮点,是因为浮点是“浮点”。在双精度数内有一个符号位,尾数为几位,指数为几位。在二进制中,升至2的幂等于将小数点移到右侧(如果您升到负数,则移到左侧)。因此,基本上,指数就是用二进制表示分数点在哪里。对双精度数据使用这种内存中表示形式的最大好处是,对于接近0的数字,您可以获得很高的精度,随着数字的增大,精度会逐渐下降。
最后一件事就是你正在发生的事情。您的电话号码太大,无法准确存储。因此,它被四舍五入为最接近的2的幂的和(2的幂是二进制全为零的数字)。
快速实验:在浏览器中按F12键,打开JavaScript控制台,然后键入49499999995499995136。就我而言,在Chrome中,我也遇到了同样的问题。
如果您真的非常想要这么大的精度,则可以尝试some of these libraries,但这对于学生程序来说太高级了,您不需要它。如果用户键入的数字太大(只需教授喜欢,实际上是很正确的话),只需添加一个if块并显示一条错误消息即可。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。